mirror of
https://github.com/lkeme/BiliHelper-personal.git
synced 2025-12-19 17:40:07 +08:00
[update] Version 0.1.0
This commit is contained in:
parent
4edfb295b4
commit
44e54d38a8
66
CHANGELOG.md
66
CHANGELOG.md
@ -1,62 +1,40 @@
|
|||||||
# Release Notes
|
# Release Notes
|
||||||
# 本项目Log
|
# 本项目Log
|
||||||
|
|
||||||
## v0.0.1.191223 alpha (2019-12-23)
|
## v0.1.0.191227 alpha (2019-12-27)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- anchor(beta)
|
- 新增备用官方分区监控
|
||||||
|
- 新增按勋章亲密度赠送
|
||||||
|
- 新增天选时刻获奖推送
|
||||||
-
|
-
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- 优化部分架构
|
||||||
|
- 优化独立监控
|
||||||
|
- 优化监控逻辑
|
||||||
|
- 优化礼物赠送
|
||||||
|
- 优化通用抽奖
|
||||||
|
- 优化推送逻辑
|
||||||
-
|
-
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- 修复部分日志显示
|
||||||
|
- 修复数据统计异常
|
||||||
|
- 修复瓜子宝箱异常
|
||||||
|
- 修复Server酱异常
|
||||||
|
- 修复天选时刻异常
|
||||||
|
- 修复抽奖数据异常
|
||||||
|
- 修复部分已知BUG
|
||||||
|
- 修复获奖推送通知
|
||||||
-
|
-
|
||||||
|
|
||||||
## v0.0.1.191030 alpha (2019-10-30)
|
## v0.0.5.191223 alpha (2019-12-23)
|
||||||
|
|
||||||
### Added
|
## v0.0.4.191030 alpha (2019-10-30)
|
||||||
-
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- unify raffle api
|
|
||||||
- danmu
|
|
||||||
- captcha ocr api
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
-
|
|
||||||
|
|
||||||
## v0.0.1.190730 alpha (2019-07-30)
|
|
||||||
|
|
||||||
### Added
|
|
||||||
-
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- unify raffle api
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
-
|
|
||||||
|
|
||||||
## v0.0.1.190723 alpha (2019-07-23)
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- pk lottery
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
-
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
-
|
|
||||||
|
|
||||||
|
## v0.0.3.190730 alpha (2019-07-30)
|
||||||
|
|
||||||
|
## v0.0.2.190723 alpha (2019-07-23)
|
||||||
|
|
||||||
## v0.0.1.190713 alpha (2019-07-13)
|
## v0.0.1.190713 alpha (2019-07-13)
|
||||||
|
|
||||||
### Added
|
|
||||||
- Initialization
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Initialization
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Initialization
|
|
||||||
|
|||||||
76
DOC.md
76
DOC.md
@ -2,7 +2,7 @@
|
|||||||
<p align="center"><img width="300px" src="https://i.loli.net/2018/04/20/5ad97bd395912.jpeg"></p>
|
<p align="center"><img width="300px" src="https://i.loli.net/2018/04/20/5ad97bd395912.jpeg"></p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://img.shields.io/badge/version-0.0.1.191213 alpha-green.svg?longCache=true&style=for-the-badge">
|
<img src="https://img.shields.io/badge/version-0.1.0.191227 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">
|
<img src="https://img.shields.io/badge/license-mit-blue.svg?longCache=true&style=for-the-badge">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -17,35 +17,40 @@ B 站直播实用脚本
|
|||||||
|
|
||||||
|plugin |version |description |
|
|plugin |version |description |
|
||||||
|--------------------|--------------------|--------------------|
|
|--------------------|--------------------|--------------------|
|
||||||
|Daily |19.12.23 |每日背包奖励 |
|
|Login |19.12.27 |账号登录 |
|
||||||
|GiftSend |19.12.23 |自动清空过期礼物 |
|
|Sleep |19.12.27 |休眠控制 |
|
||||||
|Heart |19.12.23 |双端直播间心跳 |
|
|MasterSite |19.12.27 |主站助手 |
|
||||||
|Login |19.12.23 |帐号登录组件 |
|
|Daily |19.12.27 |每日礼包 |
|
||||||
|Silver |19.12.23 |自动领宝箱 |
|
|Heart |19.12.27 |双端心跳 |
|
||||||
|Task |19.12.23 |每日任务 |
|
|Task |19.12.27 |每日任务 |
|
||||||
|GiftHeart |19.12.23 |心跳礼物 |
|
|Silver |19.12.27 |银瓜子宝箱 |
|
||||||
|Silver2Coin |19.12.23 |银瓜子换硬币 |
|
|Barrage |19.12.27 |活跃弹幕 |
|
||||||
|MaterialObject |19.12.23 |实物抽奖 |
|
|Silver2Coin |19.12.27 |银瓜子换硬币 |
|
||||||
|GroupSignIn |19.12.23 |应援团签到 |
|
|GiftSend |19.12.27 |礼物赠送 |
|
||||||
|Storm |19.12.23 |节奏风暴 |
|
|GroupSignIn |19.12.27 |友爱社签到 |
|
||||||
|Notice |19.12.23 |Server酱 |
|
|GiftHeart |19.12.27 |心跳礼物 |
|
||||||
|UnifyRaffle |19.12.23 |统一活动抽奖 |
|
|MaterialObject |19.12.27 |实物抽奖 |
|
||||||
|MasterSite |19.12.23 |主站(观看、分享、投币)|
|
|AloneTcpClient |19.12.27 |独立监控 |
|
||||||
|Guard |19.12.23 |舰长上船亲密度 |
|
|ZoneTcpClient |19.12.27 |分区监控 |
|
||||||
|PkRaffle |19.12.23 |大乱斗 |
|
|StormRaffle |19.12.27 |节奏风暴 |
|
||||||
|Anchor |19.12.23 |天选时刻 |
|
|GiftRaffle |19.12.27 |活动礼物 |
|
||||||
|
|PkRaffle |19.12.27 |大乱斗 |
|
||||||
|
|GuardRaffle |19.12.27 |舰长总督 |
|
||||||
|
|AnchorRaffle |19.12.27 |天选时刻 |
|
||||||
|
|AwardRecord |19.12.27 |获奖通知 |
|
||||||
|
|Statistics |19.12.27 |数据统计 |
|
||||||
|
|
||||||
## 打赏赞助
|
## 打赏赞助
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
> 待添加
|
||||||
|
|
||||||
## 未完成功能
|
## 未完成功能
|
||||||
|
|
||||||
|待续 |
|
|待续 |
|
||||||
|-----------|
|
|-----------|
|
||||||
|添加多用户 |
|
|多用户 |
|
||||||
|待添加 |
|
|
||||||
|
|
||||||
## 环境依赖
|
## 环境依赖
|
||||||
|
|
||||||
@ -58,7 +63,6 @@ B 站直播实用脚本
|
|||||||
|php_json |
|
|php_json |
|
||||||
|php_zlib |
|
|php_zlib |
|
||||||
|php_mbstring |
|
|php_mbstring |
|
||||||
|待添加 |
|
|
||||||
|
|
||||||
通常使用 `composer` 工具会自动检测上述依赖问题。
|
通常使用 `composer` 工具会自动检测上述依赖问题。
|
||||||
|
|
||||||
@ -79,11 +83,7 @@ https://mirrors.cloud.tencent.com/composer/
|
|||||||
composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/
|
composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/
|
||||||
```
|
```
|
||||||
|
|
||||||
## 打赏赞助
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
> 待添加
|
|
||||||
|
|
||||||
## 使用指南
|
## 使用指南
|
||||||
|
|
||||||
@ -196,22 +196,36 @@ APP_CALLBACK="https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<CHAR_ID>&
|
|||||||
|
|
||||||
## 直播间 ID 问题
|
## 直播间 ID 问题
|
||||||
|
|
||||||
`user.conf` 文件中有个 `ROOM_ID` 配置,填写此项可以清空临过期礼物给指定直播间。
|
文件 `user.conf` 里
|
||||||
|
|
||||||
|
`ROOM_ID` 配置,填写此项可以清空临过期礼物给指定直播间。
|
||||||
|
|
||||||
|
`ROOM_LIST` 配置,使用长位直播间,填写此项可以清空临礼物给指定有勋章的直播间。
|
||||||
|
|
||||||
|
`FEED_FILL` 配置,搭配上一条使用,使用过期礼物或者倒序使用正常礼物。
|
||||||
|
|
||||||
|
`SOCKET_ROOM_ID` 配置,监控使用,暂时没用到。
|
||||||
|
|
||||||
通常可以在直播间页面的 url 获取到它
|
通常可以在直播间页面的 url 获取到它
|
||||||
```
|
```
|
||||||
http://live.bilibili.com/9522051
|
http://live.bilibili.com/9522051
|
||||||
```
|
```
|
||||||
|
|
||||||
所有直播间号码小于 1000 的直播间为短号,该脚本在每次启动会自动修正,无需关心,
|
长位直播间ID获取
|
||||||
|
```
|
||||||
|
https://api.live.bilibili.com/room/v1/Room/room_init?id=3
|
||||||
|
```
|
||||||
|
|
||||||
|
所有直播间号码小于 1000 的直播间为短号,该脚本在每次启动会自动修正部分功能,特殊标注的请留意,
|
||||||
|
|
||||||
## 相关
|
## 相关
|
||||||
|
|
||||||
> 本项目基于[BilibiliHelper](https://github.com/metowolf/BilibiliHelper)项目
|
> [BilibiliHelper](https://github.com/metowolf/BilibiliHelper)
|
||||||
|
|
||||||
> 基于父项目的架构开发,在此感谢父项目的开发
|
> [BiliHelper](https://github.com/lkeme/BiliHelper)
|
||||||
|
|
||||||
|
> [Github](https://github.com/)
|
||||||
|
|
||||||
> 保留父项目没必要修改的信息,另外欢迎重构(Haha)
|
|
||||||
|
|
||||||
## License 许可证
|
## License 许可证
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg)
|
|||||||
|
|
||||||
## 公告
|
## 公告
|
||||||
|
|
||||||
Currently for Personal Edition **0.0.1.191213 alpha**
|
Currently for Personal Edition **0.1.0.191227 alpha**
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
|
|
||||||
|
|||||||
@ -10,10 +10,10 @@
|
|||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-zlib": "*",
|
"ext-zlib": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"vlucas/phpdotenv": "^2.4",
|
|
||||||
"monolog/monolog": "^1.23",
|
"monolog/monolog": "^1.23",
|
||||||
"bramus/monolog-colored-line-formatter": "^2.0",
|
"bramus/monolog-colored-line-formatter": "^2.0",
|
||||||
"clue/socket-raw": "^1.4.1"
|
"clue/socket-raw": "^1.4.1",
|
||||||
|
"vlucas/phpdotenv": "^4.1"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"authors": [
|
||||||
@ -25,7 +25,9 @@
|
|||||||
],
|
],
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"lkeme\\BiliHelper\\": "src/"
|
"BiliHelper\\Core\\": "src/core",
|
||||||
|
"BiliHelper\\Plugin\\": "src/plugin",
|
||||||
|
"BiliHelper\\Util\\": "src/util"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
88
composer.lock
generated
88
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d09e06835f7ff6a06fcb74285e6617c5",
|
"content-hash": "6034c5a467eb270c2c7d1ce12d7277fd",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bramus/ansi-php",
|
"name": "bramus/ansi-php",
|
||||||
@ -245,6 +245,67 @@
|
|||||||
],
|
],
|
||||||
"time": "2019-12-20T14:15:16+00:00"
|
"time": "2019-12-20T14:15:16+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "phpoption/phpoption",
|
||||||
|
"version": "1.7.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/schmittjoh/php-option.git",
|
||||||
|
"reference": "77f7c4d2e65413aff5b5a8cc8b3caf7a28d81959"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/77f7c4d2e65413aff5b5a8cc8b3caf7a28d81959",
|
||||||
|
"reference": "77f7c4d2e65413aff5b5a8cc8b3caf7a28d81959",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^5.5.9 || ^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"bamarni/composer-bin-plugin": "^1.3",
|
||||||
|
"phpunit/phpunit": "^4.8.35 || ^5.0 || ^6.0 || ^7.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"
|
||||||
|
],
|
||||||
|
"time": "2019-12-15T19:35:24+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@ -364,16 +425,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "vlucas/phpdotenv",
|
"name": "vlucas/phpdotenv",
|
||||||
"version": "v2.6.1",
|
"version": "v4.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/vlucas/phpdotenv.git",
|
"url": "https://github.com/vlucas/phpdotenv.git",
|
||||||
"reference": "2a7dcf7e3e02dc5e701004e51a6f304b713107d5"
|
"reference": "0176075a1b7ee9cf86f70143ec79edf7072c975a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2a7dcf7e3e02dc5e701004e51a6f304b713107d5",
|
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/0176075a1b7ee9cf86f70143ec79edf7072c975a",
|
||||||
"reference": "2a7dcf7e3e02dc5e701004e51a6f304b713107d5",
|
"reference": "0176075a1b7ee9cf86f70143ec79edf7072c975a",
|
||||||
"shasum": "",
|
"shasum": "",
|
||||||
"mirrors": [
|
"mirrors": [
|
||||||
{
|
{
|
||||||
@ -383,16 +444,18 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9",
|
"php": "^5.5.9 || ^7.0",
|
||||||
|
"phpoption/phpoption": "^1.7.1",
|
||||||
"symfony/polyfill-ctype": "^1.9"
|
"symfony/polyfill-ctype": "^1.9"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^4.8.35 || ^5.0"
|
"bamarni/composer-bin-plugin": "^1.3",
|
||||||
|
"phpunit/phpunit": "^4.8.35 || ^5.0 || ^6.0 || ^7.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.6-dev"
|
"dev-master": "4.1-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -405,10 +468,15 @@
|
|||||||
"BSD-3-Clause"
|
"BSD-3-Clause"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Graham Campbell",
|
||||||
|
"email": "graham@alt-three.com",
|
||||||
|
"homepage": "https://gjcampbell.co.uk/"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Vance Lucas",
|
"name": "Vance Lucas",
|
||||||
"email": "vance@vancelucas.com",
|
"email": "vance@vancelucas.com",
|
||||||
"homepage": "http://www.vancelucas.com"
|
"homepage": "https://vancelucas.com/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
|
"description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
|
||||||
@ -417,7 +485,7 @@
|
|||||||
"env",
|
"env",
|
||||||
"environment"
|
"environment"
|
||||||
],
|
],
|
||||||
"time": "2019-01-29T11:11:52+00:00"
|
"time": "2019-12-14T13:59:29+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
|
|||||||
@ -11,32 +11,6 @@ ACCESS_TOKEN=
|
|||||||
REFRESH_TOKEN=
|
REFRESH_TOKEN=
|
||||||
COOKIE=
|
COOKIE=
|
||||||
|
|
||||||
#######################
|
|
||||||
# 固定设置 #
|
|
||||||
#######################
|
|
||||||
|
|
||||||
# 推送服务器
|
|
||||||
USE_SERVER=true
|
|
||||||
SERVER_ADDR=tcp://47.102.120.84:10010
|
|
||||||
SERVER_KEY=,*(?PVl]nIbo35sB
|
|
||||||
|
|
||||||
# SERVER酱, 用于推送消息
|
|
||||||
USE_SCKEY=
|
|
||||||
|
|
||||||
# 切换HTTPS,为真则使用https协议
|
|
||||||
USE_HTTPS=true
|
|
||||||
|
|
||||||
# 是否使用代理(前提保证有效代理)
|
|
||||||
USE_PROXY=false
|
|
||||||
PROXY_IP=127.0.0.1
|
|
||||||
PROXY_PORT=8888
|
|
||||||
|
|
||||||
# 直播间ID,用于礼物赠送
|
|
||||||
ROOM_ID=9522051
|
|
||||||
|
|
||||||
# 弹幕监控房间(为空则随机)
|
|
||||||
SOCKET_ROOM_ID=9522051
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# 功能设置 #
|
# 功能设置 #
|
||||||
#######################
|
#######################
|
||||||
@ -78,8 +52,51 @@ USE_ADD_COIN=false
|
|||||||
ADD_COIN_AV_NUM=1
|
ADD_COIN_AV_NUM=1
|
||||||
ADD_COIN_AV=33492180
|
ADD_COIN_AV=33492180
|
||||||
|
|
||||||
|
# 休眠时间|时间区间(0-23)|逗号分隔
|
||||||
|
USE_SLEEP=true
|
||||||
|
SLEEP_SECTION=2,3,4,5,6
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# 日志设置 #
|
# 基础设置 #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
# 独立推送服务(主)
|
||||||
|
USE_ALONE_SERVER=true
|
||||||
|
ALONE_SERVER_ADDR=tcp://47.102.120.84:10010
|
||||||
|
ALONE_SERVER_KEY=,*(?PVl]nIbo35sB
|
||||||
|
|
||||||
|
# 分区推送服务(备)
|
||||||
|
USE_ZONE_SERVER=false
|
||||||
|
ZONE_SERVER_ADDR=tcp://broadcastlv.chat.bilibili.com:2243/sub
|
||||||
|
|
||||||
|
# 切换HTTPS,为真则使用https协议
|
||||||
|
USE_HTTPS=true
|
||||||
|
|
||||||
|
# 是否使用代理(前提保证有效代理)
|
||||||
|
USE_PROXY=false
|
||||||
|
PROXY_IP=127.0.0.1
|
||||||
|
PROXY_PORT=8888
|
||||||
|
|
||||||
|
# SERVER酱, 用于推送消息
|
||||||
|
USE_SCKEY=
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# 房间设置 #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
# 直播间ID,用于礼物赠送
|
||||||
|
ROOM_ID=9522051
|
||||||
|
|
||||||
|
# 勋章亲密度,测试功能,使用长位房间号,左侧优先,仅支持辣条和亿元
|
||||||
|
# 是否填满(按时间投喂正常礼物,否则过期礼物)|直播间ID列表|逗号分隔
|
||||||
|
FEED_FILL=false
|
||||||
|
ROOM_LIST=9522051
|
||||||
|
|
||||||
|
# 弹幕监控房间(为空则随机)
|
||||||
|
SOCKET_ROOM_ID=9522051
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# 程序设置 #
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
# 写入日志
|
# 写入日志
|
||||||
|
|||||||
85
index.php
85
index.php
@ -8,89 +8,12 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
//autoload
|
|
||||||
require 'vendor/autoload.php';
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
use Dotenv\Dotenv;
|
|
||||||
|
|
||||||
set_time_limit(0);
|
$filename = isset($argv[1]) ? $argv[1] : 'user.conf';
|
||||||
header("Content-Type:text/html; charset=utf-8");
|
|
||||||
date_default_timezone_set('Asia/Shanghai');
|
|
||||||
|
|
||||||
class Index
|
$app = new BiliHelper\Core\App();
|
||||||
{
|
$app->load(__DIR__, $filename);
|
||||||
public static $conf_file = null;
|
$app->start();
|
||||||
public static $dotenv = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $conf_file
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public static function run($conf_file)
|
|
||||||
{
|
|
||||||
self::$conf_file = $conf_file;
|
|
||||||
self::loadConfigFile();
|
|
||||||
while (true) {
|
|
||||||
if (!Login::check()) {
|
|
||||||
self::$dotenv->overload();
|
|
||||||
}
|
|
||||||
Daily::run();
|
|
||||||
MasterSite::run();
|
|
||||||
Danmu::run();
|
|
||||||
GiftSend::run();
|
|
||||||
Heart::run();
|
|
||||||
Silver::run();
|
|
||||||
Task::run();
|
|
||||||
Silver2Coin::run();
|
|
||||||
GroupSignIn::run();
|
|
||||||
Live::run();
|
|
||||||
GiftHeart::run();
|
|
||||||
Winning::run();
|
|
||||||
MaterialObject::run();
|
|
||||||
TcpClient::run();
|
|
||||||
Storm::run();
|
|
||||||
PkRaffle::run();
|
|
||||||
UnifyRaffle::run();
|
|
||||||
Guard::run();
|
|
||||||
Anchor::run();
|
|
||||||
Statistics::run();
|
|
||||||
usleep(0.2 * 1000000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function loadConfigFile()
|
|
||||||
{
|
|
||||||
$file_path = __DIR__ . '/conf/' . self::$conf_file;
|
|
||||||
|
|
||||||
if (is_file($file_path) && self::$conf_file != 'user.conf') {
|
|
||||||
$load_files = [
|
|
||||||
self::$conf_file,
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$default_file_path = __DIR__ . '/conf/user.conf';
|
|
||||||
if (!is_file($default_file_path)) {
|
|
||||||
exit('默认加载配置文件不存在,请按照文档添加配置文件!');
|
|
||||||
}
|
|
||||||
|
|
||||||
$load_files = [
|
|
||||||
'user.conf',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
foreach ($load_files as $load_file) {
|
|
||||||
self::$dotenv = new Dotenv(__DIR__ . '/conf', $load_file);
|
|
||||||
self::$dotenv->load();
|
|
||||||
}
|
|
||||||
|
|
||||||
// load ACCESS_KEY
|
|
||||||
Login::run();
|
|
||||||
self::$dotenv->overload();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOAD
|
|
||||||
$conf_file = isset($argv[1]) ? $argv[1] : 'user.conf';
|
|
||||||
// RUN
|
|
||||||
Index::run($conf_file);
|
|
||||||
|
|||||||
31
src/File.php
31
src/File.php
@ -1,31 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class File
|
|
||||||
{
|
|
||||||
// RUN
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// PUT CONF
|
|
||||||
public static function writeNewEnvironmentFileWith($key, $value)
|
|
||||||
{
|
|
||||||
file_put_contents(__DIR__ . '/../conf/' . Index::$conf_file, preg_replace(
|
|
||||||
'/^' . $key . '=' . getenv($key) . '/m',
|
|
||||||
$key . '=' . $value,
|
|
||||||
file_get_contents(__DIR__ . '/../conf/' . Index::$conf_file)
|
|
||||||
));
|
|
||||||
// 写入系统变量
|
|
||||||
putenv($key . '=' . $value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
112
src/GiftSend.php
112
src/GiftSend.php
@ -1,112 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class GiftSend
|
|
||||||
{
|
|
||||||
public static $lock = 0;
|
|
||||||
protected static $uid = 0;
|
|
||||||
protected static $ruid = 0;
|
|
||||||
protected static $roomid = 0;
|
|
||||||
|
|
||||||
protected static function getRoomInfo()
|
|
||||||
{
|
|
||||||
Log::info('正在生成直播间信息...');
|
|
||||||
|
|
||||||
$payload = [];
|
|
||||||
$data = Curl::get('https://account.bilibili.com/api/myinfo/v2', Sign::api($payload));
|
|
||||||
$data = json_decode($data, true);
|
|
||||||
|
|
||||||
if (isset($data['code']) && $data['code']) {
|
|
||||||
Log::warning('获取帐号信息失败!', ['msg' => $data['message']]);
|
|
||||||
Log::warning('清空礼物功能禁用!');
|
|
||||||
self::$lock = time() + 100000000;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$uid = $data['mid'];
|
|
||||||
|
|
||||||
$payload = [
|
|
||||||
'id' => getenv('ROOM_ID'),
|
|
||||||
];
|
|
||||||
$data = Curl::get('https://api.live.bilibili.com/room/v1/Room/get_info', Sign::api($payload));
|
|
||||||
$data = json_decode($data, true);
|
|
||||||
|
|
||||||
if (isset($data['code']) && $data['code']) {
|
|
||||||
Log::warning('获取主播房间号失败!', ['msg' => $data['message']]);
|
|
||||||
Log::warning('清空礼物功能禁用!');
|
|
||||||
self::$lock = time() + 100000000;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::info('直播间信息生成完毕!');
|
|
||||||
|
|
||||||
self::$ruid = $data['data']['uid'];
|
|
||||||
self::$roomid = $data['data']['room_id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
if (empty(self::$ruid)) {
|
|
||||||
self::getRoomInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self::$lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$payload = [];
|
|
||||||
$data = Curl::get('https://api.live.bilibili.com/gift/v2/gift/bag_list', Sign::api($payload));
|
|
||||||
$data = json_decode($data, true);
|
|
||||||
|
|
||||||
if (isset($data['code']) && $data['code']) {
|
|
||||||
Log::warning('背包查看失败!', ['msg' => $data['message']]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($data['data']['list'])) {
|
|
||||||
foreach ($data['data']['list'] as $vo) {
|
|
||||||
if ($vo['corner_mark'] == '永久'){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($vo['expire_at'] >= $data['data']['time'] && $vo['expire_at'] <= $data['data']['time'] + 3600) {
|
|
||||||
self::send($vo);
|
|
||||||
sleep(3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$lock = time() + 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function send($value)
|
|
||||||
{
|
|
||||||
$payload = [
|
|
||||||
'coin_type' => 'silver',
|
|
||||||
'gift_id' => $value['gift_id'],
|
|
||||||
'ruid' => self::$ruid,
|
|
||||||
'uid' => self::$uid,
|
|
||||||
'biz_id' => self::$roomid,
|
|
||||||
'gift_num' => $value['gift_num'],
|
|
||||||
'data_source_id' => '',
|
|
||||||
'data_behavior_id' => '',
|
|
||||||
'bag_id' => $value['bag_id']
|
|
||||||
];
|
|
||||||
|
|
||||||
$data = Curl::post('https://api.live.bilibili.com/gift/v2/live/bag_send', Sign::api($payload));
|
|
||||||
$data = json_decode($data, true);
|
|
||||||
|
|
||||||
if (isset($data['code']) && $data['code']) {
|
|
||||||
Log::warning('送礼失败!', ['msg' => $data['message']]);
|
|
||||||
} else {
|
|
||||||
Log::notice("成功向 {$payload['biz_id']} 投喂了 {$value['gift_num']} 个{$value['gift_name']}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
124
src/Guard.php
124
src/Guard.php
@ -1,124 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class Guard
|
|
||||||
{
|
|
||||||
const ACTIVE_TITLE = '总督舰长';
|
|
||||||
const ACTIVE_SWITCH = 'USE_GUARD';
|
|
||||||
|
|
||||||
public static $lock = 0;
|
|
||||||
|
|
||||||
protected static $wait_list = [];
|
|
||||||
protected static $all_list = [];
|
|
||||||
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
if (getenv(self::ACTIVE_SWITCH) == 'false') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (self::$lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::startLottery();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 抽奖逻辑
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected static function startLottery(): bool
|
|
||||||
{
|
|
||||||
$max_num = 3;
|
|
||||||
while ($max_num) {
|
|
||||||
$guard = array_shift(self::$wait_list);
|
|
||||||
if (is_null($guard)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$guard_lid = $guard['lid'];
|
|
||||||
$guard_rid = $guard['rid'];
|
|
||||||
Live::goToRoom($guard_rid);
|
|
||||||
Statistics::addJoinList(self::ACTIVE_TITLE);
|
|
||||||
$data = self::lottery($guard_rid, $guard_lid);
|
|
||||||
if ($data['code'] == 0) {
|
|
||||||
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
|
||||||
Log::notice("房间 {$guard_rid} 编号 {$guard_lid} " . self::ACTIVE_TITLE . ": {$data['data']['message']}");
|
|
||||||
} elseif ($data['code'] == 400 && $data['msg'] == '你已经领取过啦') {
|
|
||||||
Log::info("房间 {$guard_rid} 编号 {$guard_lid} " . self::ACTIVE_TITLE . ": {$data['msg']}");
|
|
||||||
} else {
|
|
||||||
Log::warning("房间 {$guard_rid} 编号 {$guard_lid} " . self::ACTIVE_TITLE . ": {$data['msg']}");
|
|
||||||
}
|
|
||||||
$max_num--;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求抽奖
|
|
||||||
* @param $rid
|
|
||||||
* @param $lid
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private static function lottery($rid, $lid): array
|
|
||||||
{
|
|
||||||
$user_info = User::parseCookies();
|
|
||||||
$url = "https://api.live.bilibili.com/lottery/v2/lottery/join";
|
|
||||||
$payload = [
|
|
||||||
"roomid" => $rid,
|
|
||||||
"id" => $lid,
|
|
||||||
"type" => "guard",
|
|
||||||
"csrf_token" => $user_info['token']
|
|
||||||
];
|
|
||||||
$raw = Curl::post($url, Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
return $de_raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重复检测
|
|
||||||
* @param int $lid
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private static function toRepeatLid(int $lid): bool
|
|
||||||
{
|
|
||||||
if (in_array($lid, self::$all_list)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (count(self::$all_list) > 2000) {
|
|
||||||
self::$all_list = [];
|
|
||||||
}
|
|
||||||
array_push(self::$all_list, $lid);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据推入队列
|
|
||||||
* @param array $data
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function pushToQueue(array $data): bool
|
|
||||||
{
|
|
||||||
if (getenv(self::ACTIVE_SWITCH) == 'false') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (self::toRepeatLid($data['lid'])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Statistics::addPushList(self::ACTIVE_TITLE);
|
|
||||||
self::$wait_list = array_merge(self::$wait_list, [['rid' => $data['rid'], 'lid' => $data['lid']]]);
|
|
||||||
$wait_num = count(self::$wait_list);
|
|
||||||
if ($wait_num > 2) {
|
|
||||||
Log::info("当前队列中共有 {$wait_num} 个" . self::ACTIVE_TITLE . "待抽奖");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
154
src/Live.php
154
src/Live.php
@ -1,154 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class Live
|
|
||||||
{
|
|
||||||
public static $lock = 0;
|
|
||||||
|
|
||||||
// RUN
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
self::isSleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET RANDOW ROOM_ID
|
|
||||||
public static function getUserRecommend()
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
$raw = Curl::get('https://api.live.bilibili.com/area/liveList?area=all&order=online&page=' . random_int(0, 5));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
if ($de_raw['code'] != '0') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$rand_num = random_int(1, 29);
|
|
||||||
|
|
||||||
return $de_raw['data'][$rand_num]['roomid'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET REALROOM_ID
|
|
||||||
public static function getRealRoomID($room_id)
|
|
||||||
{
|
|
||||||
$raw = Curl::get('https://api.live.bilibili.com/room/v1/Room/room_init?id=' . $room_id);
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
if ($de_raw['code']) {
|
|
||||||
Log::warning($room_id . ' : ' . $de_raw['msg']);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($de_raw['data']['is_hidden']) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($de_raw['data']['is_locked']) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($de_raw['data']['encrypted']) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $de_raw['data']['room_id'];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 钓鱼检测
|
|
||||||
public static function fishingDetection($room_id): bool
|
|
||||||
{
|
|
||||||
if (self::getRealRoomID($room_id)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// RANDOM DELAY
|
|
||||||
public static function randFloat($min = 0, $max = 3): bool
|
|
||||||
{
|
|
||||||
$rand = $min + mt_rand() / mt_getrandmax() * ($max - $min);
|
|
||||||
sleep($rand);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TO ROOM
|
|
||||||
public static function goToRoom($room_id): bool
|
|
||||||
{
|
|
||||||
$payload = [
|
|
||||||
'room_id' => $room_id,
|
|
||||||
];
|
|
||||||
Curl::post('https://api.live.bilibili.com/room/v1/Room/room_entry_action', Sign::api($payload));
|
|
||||||
// Log::info('进入直播间[' . $room_id . ']抽奖!');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get Millisecond
|
|
||||||
public static function getMillisecond()
|
|
||||||
{
|
|
||||||
list($t1, $t2) = explode(' ', microtime());
|
|
||||||
return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IS SLEEP
|
|
||||||
public static function isSleep()
|
|
||||||
{
|
|
||||||
if (self::$lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::$lock = time() + 5 * 60;
|
|
||||||
|
|
||||||
$hour = date('H');
|
|
||||||
if ($hour >= 2 && $hour < 6) {
|
|
||||||
self::bannedVisit('sleep');
|
|
||||||
Log::warning('休眠时间,暂停非必要任务,4小时后自动开启!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$payload = [];
|
|
||||||
$raw = Curl::get('https://api.live.bilibili.com/mobile/freeSilverAward', Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
if ($de_raw['msg'] == '访问被拒绝') {
|
|
||||||
self::bannedVisit('ban');
|
|
||||||
Log::warning('账号拒绝访问,暂停非必要任务,凌晨自动开启!');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//被封禁访问
|
|
||||||
public static function bannedVisit($arg)
|
|
||||||
{
|
|
||||||
//获取当前时间
|
|
||||||
$block_time = strtotime(date("Y-m-d H:i:s"));
|
|
||||||
|
|
||||||
if ($arg == 'ban') {
|
|
||||||
$unblock_time = strtotime(date("Y-m-d", strtotime("+1 day", $block_time)));
|
|
||||||
} elseif ($arg == 'sleep') {
|
|
||||||
// TODO
|
|
||||||
$unblock_time = $block_time + 4 * 60 * 60;
|
|
||||||
} else {
|
|
||||||
$unblock_time = time();
|
|
||||||
}
|
|
||||||
|
|
||||||
$second = time() + ceil($unblock_time - $block_time) + 5 * 60;
|
|
||||||
$hour = floor(($second - time()) / 60 / 60);
|
|
||||||
|
|
||||||
if ($arg == 'ban') {
|
|
||||||
// 推送被ban信息
|
|
||||||
Notice::run('banned', $hour);
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$lock = $second;
|
|
||||||
|
|
||||||
Silver::$lock = $second;
|
|
||||||
MaterialObject::$lock = $second;
|
|
||||||
GiftHeart::$lock = $second;
|
|
||||||
TcpClient::$lock = $second;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
123
src/Notice.php
123
src/Notice.php
@ -1,123 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class Notice
|
|
||||||
{
|
|
||||||
protected static $type = '';
|
|
||||||
protected static $result = '';
|
|
||||||
protected static $uname = '';
|
|
||||||
protected static $sckey = '';
|
|
||||||
|
|
||||||
// RUN
|
|
||||||
public static function run($type, $result = '')
|
|
||||||
{
|
|
||||||
if (getenv('USE_SCKEY') == "") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$type = $type;
|
|
||||||
self::$result = $result;
|
|
||||||
self::$sckey = getenv('USE_SCKEY');
|
|
||||||
self::$uname = User::userInfo() ? getenv('APP_UNAME') : getenv('APP_USER');
|
|
||||||
|
|
||||||
self::infoSendManager();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 信息管理分发
|
|
||||||
private static function infoSendManager(): bool
|
|
||||||
{
|
|
||||||
$nowtime = date('Y-m-d H:i:s');
|
|
||||||
|
|
||||||
switch (self::$type) {
|
|
||||||
case 'raffle':
|
|
||||||
$info = [
|
|
||||||
'title' => '活动抽奖结果',
|
|
||||||
'content' => '[' . $nowtime . ']' . ' 用户: ' . self::$uname . ' 在活动抽奖中获得: ' . self::$result,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'storm':
|
|
||||||
$info = [
|
|
||||||
'title' => '节奏风暴中奖结果',
|
|
||||||
'content' => '[' . $nowtime . ']' . ' 用户: ' . self::$uname . ' 在节奏风暴抽奖中: ' . self::$result,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'active':
|
|
||||||
$info = [
|
|
||||||
'title' => '活动中奖结果',
|
|
||||||
'content' => '[' . $nowtime . ']' . ' 用户: ' . self::$uname . ' 在活动抽奖中获得: ' . self::$result,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'cookieRefresh':
|
|
||||||
$info = [
|
|
||||||
'title' => 'Cookie刷新',
|
|
||||||
'content' => '[' . $nowtime . ']' . ' 用户: ' . self::$uname . ' 刷新Cookie: ' . self::$result,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'loginInit':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'todaySign':
|
|
||||||
$info = [
|
|
||||||
'title' => '每日签到',
|
|
||||||
'content' => '[' . $nowtime . ']' . ' 用户: ' . self::$uname . ' 签到: ' . self::$result,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'winIng':
|
|
||||||
$info = [
|
|
||||||
'title' => '实物中奖',
|
|
||||||
'content' => '[' . $nowtime . ']' . ' 用户: ' . self::$uname . ' 实物中奖: ' . self::$result,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case 'banned':
|
|
||||||
$info = [
|
|
||||||
'title' => '账号封禁',
|
|
||||||
'content' => '[' . $nowtime . ']' . ' 用户: ' . self::$uname . ' 账号被封禁: 程序开始睡眠,凌晨自动唤醒,距离唤醒还有' . self::$result . '小时',
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
self::scSend($info);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送信息
|
|
||||||
private static function scSend($info)
|
|
||||||
{
|
|
||||||
|
|
||||||
$postdata = http_build_query(
|
|
||||||
[
|
|
||||||
'text' => $info['title'],
|
|
||||||
'desp' => $info['content']
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$opts = ['http' =>
|
|
||||||
[
|
|
||||||
'method' => 'POST',
|
|
||||||
'header' => 'Content-type: application/x-www-form-urlencoded',
|
|
||||||
'content' => $postdata
|
|
||||||
]
|
|
||||||
];
|
|
||||||
try {
|
|
||||||
$context = stream_context_create($opts);
|
|
||||||
file_get_contents('https://sc.ftqq.com/' . self::$sckey . '.send', false, $context);
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Log::warning('Server酱推送信息失败,请检查!');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
//return $result = file_get_contents('https://sc.ftqq.com/' . $this->_sckey . '.send', false, $context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
193
src/Socket.php
193
src/Socket.php
@ -1,193 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class Socket
|
|
||||||
{
|
|
||||||
protected static $socket_connection = null;
|
|
||||||
protected static $ips = [];
|
|
||||||
protected static $socket_ip = null;
|
|
||||||
protected static $socket_port = null;
|
|
||||||
public static $lock = 0;
|
|
||||||
protected static $heart_lock = 0;
|
|
||||||
|
|
||||||
// RUN
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
if (self::$lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::$lock = time() + 0.5;
|
|
||||||
|
|
||||||
self::start();
|
|
||||||
$message = self::decodeMessage();
|
|
||||||
if (!$message) {
|
|
||||||
unset($message);
|
|
||||||
self::resetConnection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$data = DataTreating::socketJsonToArray($message);
|
|
||||||
if (!$data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DataTreating::socketArrayToDispose($data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// KILL
|
|
||||||
protected static function killConnection()
|
|
||||||
{
|
|
||||||
socket_clear_error(self::$socket_connection);
|
|
||||||
socket_shutdown(self::$socket_connection);
|
|
||||||
socket_close(self::$socket_connection);
|
|
||||||
self::$socket_connection = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// RECONNECT
|
|
||||||
protected static function resetConnection()
|
|
||||||
{
|
|
||||||
$errorcode = socket_last_error();
|
|
||||||
$errormsg = socket_strerror($errorcode);
|
|
||||||
unset($errormsg);
|
|
||||||
unset($errorcode);
|
|
||||||
self::killConnection();
|
|
||||||
// Log::warning('SOCKET连接断开,5秒后重新连接...');
|
|
||||||
// sleep(5);
|
|
||||||
self::start();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SOCKET READER
|
|
||||||
protected static function readerSocket(int $length)
|
|
||||||
{
|
|
||||||
return socket_read(self::$socket_connection, $length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DECODE MESSAGE
|
|
||||||
protected static function decodeMessage()
|
|
||||||
{
|
|
||||||
$res = '';
|
|
||||||
$tmp = '';
|
|
||||||
while (1) {
|
|
||||||
while ($out = self::readerSocket(16)) {
|
|
||||||
$res = unpack('N', $out);
|
|
||||||
unset($out);
|
|
||||||
if ($res[1] != 16) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isset($res[1])) {
|
|
||||||
$length = $res[1] - 16;
|
|
||||||
if ($length > 65535) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($length <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return self::readerSocket($length);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// START
|
|
||||||
protected static function start()
|
|
||||||
{
|
|
||||||
if (is_null(self::$socket_connection)) {
|
|
||||||
$room_id = empty(getenv('SOCKET_ROOM_ID')) ? Live::getUserRecommend() : Live::getRealRoomID(getenv('SOCKET_ROOM_ID'));
|
|
||||||
$room_id = intval($room_id);
|
|
||||||
if ($room_id) {
|
|
||||||
self::getSocketServer($room_id);
|
|
||||||
self::connectServer($room_id, self::$socket_ip, self::$socket_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self::sendHeartBeatPkg();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SEND HEART
|
|
||||||
protected static function sendHeartBeatPkg()
|
|
||||||
{
|
|
||||||
if (self::$heart_lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$action_heart_beat = intval(getenv('ACTIONHEARTBEAT'));
|
|
||||||
$str = pack('NnnNN', 16, 16, 1, $action_heart_beat, 1);
|
|
||||||
socket_write(self::$socket_connection, $str, strlen($str));
|
|
||||||
Log::info('发送心跳包到弹幕服务器!');
|
|
||||||
self::$heart_lock = time() + 30;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SOCKET CONNECT
|
|
||||||
protected static function connectServer($room_id, $ip, $port)
|
|
||||||
{
|
|
||||||
$falg = 10;
|
|
||||||
while ($falg) {
|
|
||||||
try {
|
|
||||||
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
|
||||||
socket_connect($socket, $ip, $port);
|
|
||||||
$str = self::packMsg($room_id);
|
|
||||||
socket_write($socket, $str, strlen($str));
|
|
||||||
self::$socket_connection = $socket;
|
|
||||||
// TODO
|
|
||||||
Log::info("连接到弹幕服务器[{$room_id}]成功!");
|
|
||||||
return;
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Log::info("连接到弹幕服务器[{$room_id}]失败!");
|
|
||||||
Log::warning($e);
|
|
||||||
$falg -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log::info("连接弹幕服务器[{$room_id}]错误次数过多,检查网络!");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// PACK DATA
|
|
||||||
protected static function packMsg($room_id)
|
|
||||||
{
|
|
||||||
$action_entry = intval(getenv('ACTIONENTRY'));
|
|
||||||
$data = sprintf("{\"uid\":%d%08d,\"roomid\":%d}",
|
|
||||||
random_int(1000000, 2999999),
|
|
||||||
random_int(0, 99999999),
|
|
||||||
intval($room_id)
|
|
||||||
);
|
|
||||||
return pack('NnnNN', 16 + strlen($data), 16, 1, $action_entry, 1) . $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET SERVER
|
|
||||||
protected static function getSocketServer(int $room_id): bool
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
try {
|
|
||||||
$payload = [
|
|
||||||
'room_id' => $room_id,
|
|
||||||
];
|
|
||||||
$data = Curl::get('https://api.live.bilibili.com/room/v1/Danmu/getConf', Sign::api($payload));
|
|
||||||
$data = json_decode($data, true);
|
|
||||||
|
|
||||||
// TODO 判断
|
|
||||||
if (isset($data['code']) && $data['code']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$socket_ip = gethostbyname($data['data']['host']);
|
|
||||||
self::$socket_port = $data['data']['port'];
|
|
||||||
|
|
||||||
break;
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Log::warning("获取弹幕服务器出错,错误信息[{$e}]!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
201
src/Storm.php
201
src/Storm.php
@ -1,201 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class Storm
|
|
||||||
{
|
|
||||||
const ACTIVE_TITLE = '节奏风暴';
|
|
||||||
const ACTIVE_SWITCH = 'USE_STORM';
|
|
||||||
|
|
||||||
public static $lock = 0;
|
|
||||||
|
|
||||||
protected static $wait_list = [];
|
|
||||||
protected static $all_list = [];
|
|
||||||
|
|
||||||
private static $drop_rate = null;
|
|
||||||
private static $attempt = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
if (getenv(self::ACTIVE_SWITCH) == 'false') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (self::$lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::init();
|
|
||||||
self::startLottery();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function init()
|
|
||||||
{
|
|
||||||
if (!is_null(self::$attempt) && !is_null(self::$drop_rate)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO 信息不完整, 请检查配置文件 没有严格校验
|
|
||||||
self::$drop_rate = getenv('STORM_DROPRATE') !== "" ? (int)getenv('STORM_DROPRATE') : 0;
|
|
||||||
self::$attempt = getenv('STORM_ATTEMPT') !== "" ? explode(',', getenv('STORM_ATTEMPT')) : [30, 50];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 抽奖逻辑
|
|
||||||
* @return bool
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected static function startLottery(): bool
|
|
||||||
{
|
|
||||||
while (true) {
|
|
||||||
$storm = array_shift(self::$wait_list);
|
|
||||||
if (is_null($storm)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 丢弃
|
|
||||||
if (mt_rand(1, 100) <= (int)self::$drop_rate) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$storm_lid = $storm['lid'];
|
|
||||||
$storm_rid = $storm['rid'];
|
|
||||||
Live::goToRoom($storm_rid);
|
|
||||||
Statistics::addJoinList(self::ACTIVE_TITLE);
|
|
||||||
$num = random_int((int)self::$attempt[0], (int)self::$attempt[1]);
|
|
||||||
for ($i = 1; $i < $num; $i++) {
|
|
||||||
if (!self::lottery($storm_rid, $storm_lid, $i)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化日志输出
|
|
||||||
* @param $id
|
|
||||||
* @param $num
|
|
||||||
* @param $info
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function formatInfo($id, $num, $info): string
|
|
||||||
{
|
|
||||||
return "风暴 {$id} 请求 {$num} 状态 {$info}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求抽奖
|
|
||||||
* @param $rid
|
|
||||||
* @param $lid
|
|
||||||
* @param $num
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected static function lottery($rid, $lid, $num): bool
|
|
||||||
{
|
|
||||||
$user_info = User::parseCookies();
|
|
||||||
$payload = [
|
|
||||||
"id" => $lid,
|
|
||||||
"color" => "16772431",
|
|
||||||
"roomid" => $rid,
|
|
||||||
"captcha_token" => "",
|
|
||||||
"captcha_phrase" => "",
|
|
||||||
"token" => $user_info['token'],
|
|
||||||
"csrf_token" => $user_info['token'],
|
|
||||||
"visit_id" => "",
|
|
||||||
];
|
|
||||||
$raw = Curl::post('https://api.live.bilibili.com/lottery/v1/Storm/join', Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
if ($de_raw['code'] == 429 || $de_raw['code'] == -429) {
|
|
||||||
Log::notice(self::formatInfo($lid, $num, '节奏风暴未实名或异常验证码'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (isset($de_raw['data']) && empty($de_raw['data'])) {
|
|
||||||
Log::notice(self::formatInfo($lid, $num, '节奏风暴在小黑屋'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($de_raw['code'] == 0) {
|
|
||||||
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
|
||||||
Log::notice(self::formatInfo($lid, $num, $de_raw['data']['mobile_content']));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($de_raw['msg'] == '节奏风暴不存在') {
|
|
||||||
Log::notice(self::formatInfo($lid, $num, '节奏风暴已结束'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($de_raw['msg'] == '已经领取奖励') {
|
|
||||||
Log::notice(self::formatInfo($lid, $num, '节奏风暴已经领取'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($de_raw['msg'] == '你错过了奖励,下次要更快一点哦~') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Log::notice(self::formatInfo($lid, $num, $de_raw['msg']));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查ID
|
|
||||||
* @param $room_id
|
|
||||||
* @return array|bool
|
|
||||||
*/
|
|
||||||
protected static function stormCheckId($room_id)
|
|
||||||
{
|
|
||||||
$raw = Curl::get('https://api.live.bilibili.com/lottery/v1/Storm/check?roomid=' . $room_id);
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
|
|
||||||
if (empty($de_raw['data']) || $de_raw['data']['hasJoin'] != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
'id' => $de_raw['data']['id'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重复检测
|
|
||||||
* @param $lid
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private static function toRepeatLid($lid): bool
|
|
||||||
{
|
|
||||||
if (in_array($lid, self::$all_list)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (count(self::$all_list) > 2000) {
|
|
||||||
self::$all_list = [];
|
|
||||||
}
|
|
||||||
array_push(self::$all_list, $lid);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据推入队列
|
|
||||||
* @param array $data
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function pushToQueue(array $data): bool
|
|
||||||
{
|
|
||||||
if (getenv(self::ACTIVE_SWITCH) == 'false') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (self::toRepeatLid($data['lid'])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Statistics::addPushList(self::ACTIVE_TITLE);
|
|
||||||
self::$wait_list = array_merge(self::$wait_list, [['rid' => $data['rid'], 'lid' => $data['lid']]]);
|
|
||||||
$wait_num = count(self::$wait_list);
|
|
||||||
if ($wait_num > 2) {
|
|
||||||
Log::info("当前队列中共有 {$wait_num} 个" . self::ACTIVE_TITLE . "待抽奖");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class UnifyRaffle extends BaseRaffle
|
|
||||||
{
|
|
||||||
const ACTIVE_TITLE = '统一活动';
|
|
||||||
const ACTIVE_SWITCH = 'USE_ACTIVE';
|
|
||||||
|
|
||||||
public static $lock = 0;
|
|
||||||
public static $rw_lock = 0;
|
|
||||||
|
|
||||||
protected static $wait_list = [];
|
|
||||||
protected static $finish_list = [];
|
|
||||||
protected static $all_list = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查抽奖列表
|
|
||||||
* @param $rid
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected static function check($rid): bool
|
|
||||||
{
|
|
||||||
$payload = [
|
|
||||||
'roomid' => $rid
|
|
||||||
];
|
|
||||||
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v3/smalltv/Check';
|
|
||||||
$raw = Curl::get($url, Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
|
|
||||||
// 计数 && 跳出
|
|
||||||
$total = count($de_raw['data']['list']);
|
|
||||||
if (!$total) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = 0; $i < $total; $i++) {
|
|
||||||
/**
|
|
||||||
* raffleId : 88995
|
|
||||||
* title : C位光环抽奖
|
|
||||||
* type : GIFT_30013
|
|
||||||
*/
|
|
||||||
$data = [
|
|
||||||
'raffle_id' => $de_raw['data']['list'][$i]['raffleId'],
|
|
||||||
'title' => $de_raw['data']['list'][$i]['title'],
|
|
||||||
'type' => $de_raw['data']['list'][$i]['type'],
|
|
||||||
'wait' => $de_raw['data']['list'][$i]['time_wait'] + strtotime(date("Y-m-d H:i:s")),
|
|
||||||
'room_id' => $rid,
|
|
||||||
];
|
|
||||||
if (static::toRepeatLid($data['raffle_id'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Statistics::addPushList(static::ACTIVE_TITLE);
|
|
||||||
array_push(static::$wait_list, $data);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use WEB中奖查询
|
|
||||||
*/
|
|
||||||
public static function resultWeb()
|
|
||||||
{
|
|
||||||
// 时间锁
|
|
||||||
if (static::$rw_lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 如果待查询为空 && 去重
|
|
||||||
if (!count(static::$finish_list)) {
|
|
||||||
static::$rw_lock = time() + 40;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 查询,每次查询10个
|
|
||||||
$flag = 0;
|
|
||||||
foreach (static::$finish_list as $winning_web) {
|
|
||||||
$flag++;
|
|
||||||
if ($flag > 40) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 参数
|
|
||||||
$payload = [
|
|
||||||
'type' => $winning_web['type'],
|
|
||||||
'raffleId' => $winning_web['raffle_id']
|
|
||||||
];
|
|
||||||
// Web V3 Notice
|
|
||||||
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v3/smalltv/Notice';
|
|
||||||
// 请求 && 解码
|
|
||||||
$raw = Curl::get($url, Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
// 判断
|
|
||||||
switch ($de_raw['data']['status']) {
|
|
||||||
// case 3:
|
|
||||||
// break;
|
|
||||||
case 2:
|
|
||||||
Statistics::addSuccessList(static::ACTIVE_TITLE);
|
|
||||||
// 提示信息
|
|
||||||
$info = "房间 {$winning_web['room_id']} 编号 {$winning_web['raffle_id']} {$winning_web['title']}: 获得";
|
|
||||||
$info .= "{$de_raw['data']['gift_name']}X{$de_raw['data']['gift_num']}";
|
|
||||||
Log::notice($info);
|
|
||||||
// 推送活动抽奖信息
|
|
||||||
if ($de_raw['data']['gift_name'] != '辣条' && $de_raw['data']['gift_name'] != '') {
|
|
||||||
Notice::run('raffle', $info);
|
|
||||||
}
|
|
||||||
// 删除查询完成ID
|
|
||||||
unset(static::$finish_list[$flag - 1]);
|
|
||||||
static::$finish_list = array_values(static::$finish_list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static::$rw_lock = time() + 40;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 请求抽奖
|
|
||||||
* @param array $data
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected static function lottery(array $data): bool
|
|
||||||
{
|
|
||||||
$user_info = User::parseCookies();
|
|
||||||
$payload = [
|
|
||||||
'raffleId' => $data['raffle_id'],
|
|
||||||
'roomid' => $data['room_id'],
|
|
||||||
'type' => $data['type'],
|
|
||||||
'csrf_token' => $user_info['token'],
|
|
||||||
'csrf' => $user_info['token'],
|
|
||||||
'visit_id' => null,
|
|
||||||
];
|
|
||||||
// V3接口 暂做保留处理
|
|
||||||
// $url = 'https://api.live.bilibili.com/gift/v3/smalltv/join';
|
|
||||||
// $url = 'https://api.live.bilibili.com/xlive/lottery-interface/v5/smalltv/Join';
|
|
||||||
$url = 'https://api.live.bilibili.com/gift/v4/smalltv/getAward';
|
|
||||||
$raw = Curl::post($url, Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
if (isset($de_raw['code']) && $de_raw['code']) {
|
|
||||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$de_raw['message']}");
|
|
||||||
} else {
|
|
||||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$de_raw['msg']}");
|
|
||||||
array_push(static::$finish_list, $data);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,217 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
use Wrench\Client;
|
|
||||||
|
|
||||||
class Websocket
|
|
||||||
{
|
|
||||||
public static $lock = 0;
|
|
||||||
protected static $heart_lock = 0;
|
|
||||||
protected static $websocket = null;
|
|
||||||
protected static $room_id = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 入口
|
|
||||||
*/
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
if (static::$lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static::init();
|
|
||||||
static::heart();
|
|
||||||
static::receive();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 初始化
|
|
||||||
*/
|
|
||||||
protected static function init()
|
|
||||||
{
|
|
||||||
if (!static::$websocket) {
|
|
||||||
$client = new Client(
|
|
||||||
'ws://broadcastlv.chat.bilibili.com:2244/sub',
|
|
||||||
'http://live.bilibili.com'
|
|
||||||
);
|
|
||||||
static::$websocket = $client;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!static::$room_id) {
|
|
||||||
static::$room_id = empty(getenv('SOCKET_ROOM_ID')) ? Live::getUserRecommend() : Live::getRealRoomID(getenv('SOCKET_ROOM_ID'));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 连接
|
|
||||||
*/
|
|
||||||
protected static function connect()
|
|
||||||
{
|
|
||||||
Log::info("连接弹幕服务器");
|
|
||||||
if (!static::$websocket->connect()) {
|
|
||||||
Log::error('连接弹幕服务器失败');
|
|
||||||
static::$lock = time() + 60;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static::$websocket->sendData(
|
|
||||||
static::packMsg(json_encode([
|
|
||||||
'uid' => 0,
|
|
||||||
'roomid' => static::$room_id,
|
|
||||||
'protover' => 1,
|
|
||||||
'platform' => 'web',
|
|
||||||
'clientver' => '1.4.1',
|
|
||||||
]), 0x0007)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 断开连接
|
|
||||||
*/
|
|
||||||
protected static function disconnect()
|
|
||||||
{
|
|
||||||
Log::info('断开弹幕服务器');
|
|
||||||
static::$websocket->disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 读取数据
|
|
||||||
*/
|
|
||||||
protected static function receive()
|
|
||||||
{
|
|
||||||
$responses = static::$websocket->receive();
|
|
||||||
if (is_array($responses) && !empty($responses)) {
|
|
||||||
foreach ($responses as $response) {
|
|
||||||
static::split($response->getPayload());
|
|
||||||
}
|
|
||||||
static::receive();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 发送心跳
|
|
||||||
*/
|
|
||||||
protected static function heart()
|
|
||||||
{
|
|
||||||
if (!static::$websocket->isConnected()) {
|
|
||||||
static::connect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (static::$heart_lock <= time()) {
|
|
||||||
if (static::$websocket->sendData(static::packMsg('', 0x0002))) {
|
|
||||||
static::$heart_lock = time() + 30;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $id
|
|
||||||
* @return mixed|string
|
|
||||||
*/
|
|
||||||
protected static function type($id)
|
|
||||||
{
|
|
||||||
$option = [
|
|
||||||
0x0002 => 'WS_OP_HEARTBEAT',
|
|
||||||
0x0003 => 'WS_OP_HEARTBEAT_REPLY',
|
|
||||||
0x0005 => 'WS_OP_MESSAGE',
|
|
||||||
0x0007 => 'WS_OP_USER_AUTHENTICATION',
|
|
||||||
0x0008 => 'WS_OP_CONNECT_SUCCESS',
|
|
||||||
];
|
|
||||||
return isset($option[$id]) ? $option[$id] : "WS_OP_UNKNOW($id)";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $bin
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected static function split($bin)
|
|
||||||
{
|
|
||||||
if (strlen($bin)) {
|
|
||||||
$head = unpack('Npacklen/nheadlen/nver/Nop/Nseq', substr($bin, 0, 16));
|
|
||||||
$bin = substr($bin, 16);
|
|
||||||
|
|
||||||
$length = isset($head['packlen']) ? $head['packlen'] : 16;
|
|
||||||
$type = isset($head['op']) ? $head['op'] : 0x0000;
|
|
||||||
$body = substr($bin, 0, $length - 16);
|
|
||||||
|
|
||||||
Log::debug(static::type($type) . " (len=$length)");
|
|
||||||
|
|
||||||
if (($length - 16) > 65535 || ($length - 16) < 0) {
|
|
||||||
Log::notice("长度{$length}异常,重新连接服务器!");
|
|
||||||
if (static::$websocket->isConnected()) {
|
|
||||||
static::disconnect();
|
|
||||||
}
|
|
||||||
if (!static::$websocket->isConnected()) {
|
|
||||||
static::connect();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($type == 0x0005 || $type == 0x0003) {
|
|
||||||
if ($head['ver'] == 2) {
|
|
||||||
$body = gzuncompress($body);
|
|
||||||
if (substr($body, 0, 1) != '{') {
|
|
||||||
static::split($bin);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataTreating::socketJsonToArray($body);
|
|
||||||
}
|
|
||||||
|
|
||||||
$bin = substr($bin, $length - 16);
|
|
||||||
if (strlen($bin)) {
|
|
||||||
static::split($bin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $value
|
|
||||||
* @param $option
|
|
||||||
* @return string
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected static function packMsg($value, $option)
|
|
||||||
{
|
|
||||||
$head = pack('NnnNN', 0x10 + strlen($value), 0x10, 0x01, $option, 0x0001);
|
|
||||||
$str = $head . $value;
|
|
||||||
static::split($str);
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @use 写入log
|
|
||||||
* @param $message
|
|
||||||
*/
|
|
||||||
private static function writeLog($message)
|
|
||||||
{
|
|
||||||
$path = './danmu/';
|
|
||||||
if (!file_exists($path)) {
|
|
||||||
mkdir($path);
|
|
||||||
chmod($path, 0777);
|
|
||||||
}
|
|
||||||
$filename = $path . getenv('APP_USER') . ".log";
|
|
||||||
$date = date('[Y-m-d H:i:s] ');
|
|
||||||
$data = "[{$date}]{$message}" . PHP_EOL;
|
|
||||||
file_put_contents($filename, $data, FILE_APPEND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website: https://mudew.com/
|
|
||||||
* Author: Lkeme
|
|
||||||
* License: The MIT License
|
|
||||||
* Email: Useri@live.cn
|
|
||||||
* Updated: 2019 ~ 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
|
||||||
|
|
||||||
class Winning
|
|
||||||
{
|
|
||||||
public static $lock = 0;
|
|
||||||
|
|
||||||
// RUN
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
// 活动统一
|
|
||||||
UnifyRaffle::resultWeb();
|
|
||||||
|
|
||||||
// 实物
|
|
||||||
self::winningRecords();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 中奖记录
|
|
||||||
protected static function winningRecords()
|
|
||||||
{
|
|
||||||
if (self::$lock > time()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::$lock = time() + 24 * 60 * 60;
|
|
||||||
|
|
||||||
$payload = [
|
|
||||||
'page' => '1',
|
|
||||||
'month' => '',
|
|
||||||
];
|
|
||||||
$raw = Curl::post('https://api.live.bilibili.com/lottery/v1/award/award_list', Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
$month = $de_raw['data']['month_list'][0]['Ym'];
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
$payload = [
|
|
||||||
'page' => '1',
|
|
||||||
'month' => $month,
|
|
||||||
];
|
|
||||||
$raw = Curl::post('https://api.live.bilibili.com/lottery/v1/award/award_list', Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
// 没有记录
|
|
||||||
if (empty($de_raw['data']['list'])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$init_time = strtotime(date("y-m-d h:i:s")); //当前时间
|
|
||||||
foreach ($de_raw['data']['list'] as $gift) {
|
|
||||||
$next_time = strtotime($gift['create_time']); //礼物时间
|
|
||||||
$day = ceil(($init_time - $next_time) / 86400); //60s*60min*24h
|
|
||||||
|
|
||||||
if ($day <= 2 && $gift['update_time'] == '') {
|
|
||||||
$data_info = '您在: ' . $gift['create_time'] . '抽中[' . $gift['gift_name'] . 'X' . $gift['gift_num'] . ']未查看!';
|
|
||||||
Log::notice($data_info);
|
|
||||||
// TODO 推送 log
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
72
src/core/App.php
Normal file
72
src/core/App.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Core;
|
||||||
|
|
||||||
|
use BiliHelper\Plugin;
|
||||||
|
|
||||||
|
class App
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* App constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
set_time_limit(0);
|
||||||
|
header("Content-Type:text/html; charset=utf-8");
|
||||||
|
date_default_timezone_set('Asia/Shanghai');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 加载配置
|
||||||
|
* @param $app_path
|
||||||
|
* @param string $load_file
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function load($app_path, $load_file = 'user.conf')
|
||||||
|
{
|
||||||
|
// define('APP_PATH', dirname(__DIR__));
|
||||||
|
define('APP_PATH', $app_path);
|
||||||
|
Config::load($load_file);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 核心运行
|
||||||
|
*/
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
Plugin\Login::run();
|
||||||
|
Plugin\Sleep::run();
|
||||||
|
Plugin\MasterSite::run();
|
||||||
|
Plugin\Daily::run();
|
||||||
|
Plugin\Heart::run();
|
||||||
|
Plugin\Task::run();
|
||||||
|
Plugin\Silver::run();
|
||||||
|
Plugin\Barrage::run();
|
||||||
|
Plugin\Silver2Coin::run();
|
||||||
|
Plugin\GiftSend::run();
|
||||||
|
Plugin\GroupSignIn::run();
|
||||||
|
Plugin\GiftHeart::run();
|
||||||
|
Plugin\MaterialObject::run();
|
||||||
|
Plugin\AloneTcpClient::run();
|
||||||
|
Plugin\ZoneTcpClient::run();
|
||||||
|
Plugin\StormRaffle::run();
|
||||||
|
Plugin\GiftRaffle::run();
|
||||||
|
Plugin\PkRaffle::run();
|
||||||
|
Plugin\GuardRaffle::run();
|
||||||
|
Plugin\AnchorRaffle::run();
|
||||||
|
Plugin\AwardRecord::run();
|
||||||
|
Plugin\Statistics::run();
|
||||||
|
usleep(0.1 * 1000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
98
src/core/Config.php
Normal file
98
src/core/Config.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Core;
|
||||||
|
|
||||||
|
use Dotenv\Dotenv;
|
||||||
|
|
||||||
|
|
||||||
|
class Config
|
||||||
|
{
|
||||||
|
private static $app_config;
|
||||||
|
private static $config_path;
|
||||||
|
private static $instance;
|
||||||
|
|
||||||
|
public static function getInstance()
|
||||||
|
{
|
||||||
|
if (is_null(self::$instance)) {
|
||||||
|
self::$instance = new static;
|
||||||
|
}
|
||||||
|
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 加载配置文件
|
||||||
|
* @param string $load_file
|
||||||
|
*/
|
||||||
|
private static function _load($load_file)
|
||||||
|
{
|
||||||
|
$config_path = str_replace("\\", "/", APP_PATH . "/conf/{$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::$config_path = $config_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 写入配置
|
||||||
|
* @param $key
|
||||||
|
* @param $val
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function _put($key, $val)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putenv($key . '=' . $val);
|
||||||
|
// self::$app_config->load();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 读出配置
|
||||||
|
* @param string|null $key
|
||||||
|
* @return mixed|null
|
||||||
|
*/
|
||||||
|
private static function _get($key)
|
||||||
|
{
|
||||||
|
if (self::$app_config->required($key)) {
|
||||||
|
return getenv($key);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -8,7 +8,7 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Core;
|
||||||
|
|
||||||
class Curl
|
class Curl
|
||||||
{
|
{
|
||||||
@ -8,7 +8,7 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Core;
|
||||||
|
|
||||||
use Monolog\Logger;
|
use Monolog\Logger;
|
||||||
use Monolog\Handler\StreamHandler;
|
use Monolog\Handler\StreamHandler;
|
||||||
@ -8,14 +8,18 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Socket\Raw\Factory;
|
use Socket\Raw\Factory;
|
||||||
|
|
||||||
class TcpClient
|
class AloneTcpClient
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
private static $heart_lock = 0;
|
private static $heart_lock = 0;
|
||||||
private static $client = null;
|
private static $client = null;
|
||||||
private static $server_addr = null;
|
private static $server_addr = null;
|
||||||
@ -23,11 +27,11 @@ class TcpClient
|
|||||||
private static $socket_timeout = 0;
|
private static $socket_timeout = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 入口
|
* @use 入口
|
||||||
*/
|
*/
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time() || getenv('USE_SERVER') == 'false') {
|
if (self::getLock() > time() || getenv('USE_ALONE_SERVER') == 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self::init();
|
self::init();
|
||||||
@ -37,16 +41,16 @@ class TcpClient
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 初始化
|
* @use 初始化
|
||||||
*/
|
*/
|
||||||
private static function init()
|
private static function init()
|
||||||
{
|
{
|
||||||
if (empty(getenv('SERVER_ADDR')) || empty(getenv('SERVER_KEY'))) {
|
if (empty(getenv('ALONE_SERVER_ADDR')) || empty(getenv('ALONE_SERVER_KEY'))) {
|
||||||
exit('推送服务器信息不完整, 请检查配置文件!');
|
exit('推送服务器信息不完整, 请检查配置文件!');
|
||||||
}
|
}
|
||||||
if (!self::$server_addr || !self::$server_key) {
|
if (!self::$server_addr || !self::$server_key) {
|
||||||
self::$server_addr = getenv('SERVER_ADDR');
|
self::$server_addr = getenv('ALONE_SERVER_ADDR');
|
||||||
self::$server_key = getenv('SERVER_KEY');
|
self::$server_key = getenv('ALONE_SERVER_KEY');
|
||||||
}
|
}
|
||||||
if (!self::$client) {
|
if (!self::$client) {
|
||||||
self::openConnect();
|
self::openConnect();
|
||||||
@ -55,7 +59,7 @@ class TcpClient
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 数据封装
|
* @use 数据封装
|
||||||
* @param $value
|
* @param $value
|
||||||
* @param $fmt
|
* @param $fmt
|
||||||
* @return string
|
* @return string
|
||||||
@ -68,7 +72,7 @@ class TcpClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 数据解包
|
* @use 数据解包
|
||||||
* @param $value
|
* @param $value
|
||||||
* @param string $fmt
|
* @param string $fmt
|
||||||
* @return array|false
|
* @return array|false
|
||||||
@ -80,7 +84,7 @@ class TcpClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 连接认证
|
* @use 连接认证
|
||||||
*/
|
*/
|
||||||
private static function handShake()
|
private static function handShake()
|
||||||
{
|
{
|
||||||
@ -96,7 +100,7 @@ class TcpClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 心跳
|
* @use 心跳
|
||||||
*/
|
*/
|
||||||
private static function heartBeat()
|
private static function heartBeat()
|
||||||
{
|
{
|
||||||
@ -109,7 +113,7 @@ class TcpClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 读数据
|
* @use 读数据
|
||||||
* @param $length
|
* @param $length
|
||||||
* @return array|bool|false
|
* @return array|bool|false
|
||||||
*/
|
*/
|
||||||
@ -132,7 +136,7 @@ class TcpClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 写数据
|
* @use 写数据
|
||||||
* @param $data
|
* @param $data
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@ -153,7 +157,7 @@ class TcpClient
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 打开连接
|
* @use 打开连接
|
||||||
*/
|
*/
|
||||||
private static function openConnect()
|
private static function openConnect()
|
||||||
{
|
{
|
||||||
@ -166,13 +170,13 @@ class TcpClient
|
|||||||
Log::info("连接到 {$socket->getPeerName()} 推送服务器");
|
Log::info("连接到 {$socket->getPeerName()} 推送服务器");
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Log::error("连接到推送服务器失败, {$e->getMessage()}");
|
Log::error("连接到推送服务器失败, {$e->getMessage()}");
|
||||||
self::$lock = time() + 60;
|
self::setLock( 60);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 重新连接
|
* @use 重新连接
|
||||||
*/
|
*/
|
||||||
private static function reConnect()
|
private static function reConnect()
|
||||||
{
|
{
|
||||||
@ -182,7 +186,7 @@ class TcpClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc 断开连接
|
* @use 断开连接
|
||||||
*/
|
*/
|
||||||
private static function closeConnect()
|
private static function closeConnect()
|
||||||
{
|
{
|
||||||
@ -8,15 +8,18 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
class Anchor extends BaseRaffle
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class AnchorRaffle extends BaseRaffle
|
||||||
{
|
{
|
||||||
const ACTIVE_TITLE = '天选时刻';
|
const ACTIVE_TITLE = '天选时刻';
|
||||||
const ACTIVE_SWITCH = 'USE_ANCHOR';
|
const ACTIVE_SWITCH = 'USE_ANCHOR';
|
||||||
|
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
public static $rw_lock = 0;
|
|
||||||
|
|
||||||
protected static $wait_list = [];
|
protected static $wait_list = [];
|
||||||
protected static $finish_list = [];
|
protected static $finish_list = [];
|
||||||
@ -24,41 +27,45 @@ class Anchor extends BaseRaffle
|
|||||||
|
|
||||||
private static $filter_type = [];
|
private static $filter_type = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查抽奖列表
|
* @use 解析数据
|
||||||
* @param $rid
|
* @param int $room_id
|
||||||
|
* @param array $data
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected static function check($rid): bool
|
protected static function parse(int $room_id, array $data): bool
|
||||||
{
|
{
|
||||||
$payload = [
|
// 防止异常
|
||||||
'roomid' => $rid
|
if (!array_key_exists('anchor', $data['data'])) {
|
||||||
];
|
|
||||||
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v1/Anchor/Check';
|
|
||||||
$raw = Curl::get($url, Sign::api($payload));
|
|
||||||
$de_raw = json_decode($raw, true);
|
|
||||||
|
|
||||||
// 防止异常情况
|
|
||||||
if (!isset($de_raw['data']) || $de_raw['data']['join_type'] || $de_raw['data']['lot_status']) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO
|
$de_raw = $data['data']['anchor'];
|
||||||
|
if (empty($de_raw)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 无效抽奖
|
||||||
|
if ($de_raw['join_type'] || $de_raw['lot_status']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 过滤抽奖范围
|
||||||
self::$filter_type = empty(self::$filter_type) ? explode(',', getenv('ANCHOR_TYPE')) : self::$filter_type;
|
self::$filter_type = empty(self::$filter_type) ? explode(',', getenv('ANCHOR_TYPE')) : self::$filter_type;
|
||||||
if (!in_array((string)$de_raw['data']['require_type'], self::$filter_type)) {
|
if (!in_array((string)$de_raw['require_type'], self::$filter_type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// 去重
|
||||||
|
if (self::toRepeatLid($de_raw['id'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 推入列表
|
||||||
$data = [
|
$data = [
|
||||||
'room_id' => $de_raw['data']['room_id'],
|
'room_id' => $room_id,
|
||||||
'raffle_id' => $de_raw['data']['id'],
|
'raffle_id' => $de_raw['id'],
|
||||||
'prize' => $de_raw['data']['award_name'],
|
'raffle_name' => $de_raw['award_name'],
|
||||||
'wait' => strtotime(date("Y-m-d H:i:s"))
|
'wait' => time()
|
||||||
];
|
];
|
||||||
if (static::toRepeatLid($data['raffle_id'])) {
|
Statistics::addPushList(self::ACTIVE_TITLE);
|
||||||
return false;
|
array_push(self::$wait_list, $data);
|
||||||
}
|
|
||||||
Statistics::addPushList(static::ACTIVE_TITLE);
|
|
||||||
array_push(static::$wait_list, $data);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,11 +91,10 @@ class Anchor extends BaseRaffle
|
|||||||
$de_raw = json_decode($raw, true);
|
$de_raw = json_decode($raw, true);
|
||||||
|
|
||||||
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
|
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
|
||||||
print_r($de_raw);
|
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
||||||
Statistics::addSuccessList(static::ACTIVE_TITLE);
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$data['raffle_name']}");
|
||||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$data['prize']}");
|
|
||||||
} else {
|
} else {
|
||||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$de_raw['message']}");
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['message']}");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
135
src/plugin/AwardRecord.php
Normal file
135
src/plugin/AwardRecord.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class AwardRecord
|
||||||
|
{
|
||||||
|
use TimeLock;
|
||||||
|
private static $raffle_lock = 0;
|
||||||
|
private static $raffle_list = [];
|
||||||
|
private static $anchor_lock = 0;
|
||||||
|
private static $anchor_list = [];
|
||||||
|
private static $gift_lock = 0;
|
||||||
|
private static $gift_list = [];
|
||||||
|
|
||||||
|
|
||||||
|
public static function run()
|
||||||
|
{
|
||||||
|
if (self::getLock() > time()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (self::$anchor_lock < time()) {
|
||||||
|
self::anchorAward();
|
||||||
|
}
|
||||||
|
if (self::$raffle_lock < time()) {
|
||||||
|
self::raffleAward();
|
||||||
|
}
|
||||||
|
// if (self::$gift_lock < time()) {
|
||||||
|
// self::giftAward();
|
||||||
|
// }
|
||||||
|
self::setLock(5 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取天选时刻中奖纪录
|
||||||
|
*/
|
||||||
|
private static function anchorAward()
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'page' => '1',
|
||||||
|
];
|
||||||
|
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v1/Anchor/AwardRecord';
|
||||||
|
$raw = Curl::get($url, Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
// 防止异常
|
||||||
|
if (!isset($de_raw['data']) || !isset($de_raw['data']['list'])) {
|
||||||
|
Log::warning("获取天选时刻获奖记录错误: " . json_encode($de_raw, JSON_FORCE_OBJECT));
|
||||||
|
self::$anchor_lock = time() + 1 * 60 * 60;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach ($de_raw['data']['list'] as $anchor) {
|
||||||
|
$win_time = strtotime($anchor['end_time']); //礼物时间
|
||||||
|
$day = ceil((time() - $win_time) / 86400); //60s*60min*24h
|
||||||
|
// 去重
|
||||||
|
if (in_array($anchor['id'], self::$anchor_list)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 范围
|
||||||
|
if ($day <= 2) {
|
||||||
|
$info = $anchor['award_name'] . 'x' . $anchor['award_num'];
|
||||||
|
Log::notice("天选时刻于" . $anchor['end_time'] . "获奖: {$info} ,请留意查看...");
|
||||||
|
Notice::push('anchor', $info);
|
||||||
|
}
|
||||||
|
array_push(self::$anchor_list, $anchor['id']);
|
||||||
|
}
|
||||||
|
self::$anchor_lock = time() + 6 * 60 * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取实物抽奖中奖纪录
|
||||||
|
*/
|
||||||
|
private static function raffleAward()
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'page' => '1',
|
||||||
|
'month' => '',
|
||||||
|
];
|
||||||
|
$url = 'https://api.live.bilibili.com/lottery/v1/award/award_list';
|
||||||
|
$raw = Curl::get($url, Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
|
||||||
|
// 防止异常
|
||||||
|
if (!isset($de_raw['data']) || !isset($de_raw['data']['list']) || $de_raw['code']) {
|
||||||
|
Log::warning("获取实物奖励获奖记录错误: " . $de_raw['msg']);
|
||||||
|
self::$raffle_lock = time() + 1 * 60 * 60;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach ($de_raw['data']['list'] as $raffle) {
|
||||||
|
$win_time = strtotime($raffle['create_time']); //礼物时间
|
||||||
|
$day = ceil((time() - $win_time) / 86400); //60s*60min*24h
|
||||||
|
// 去重
|
||||||
|
if (in_array($raffle['id'], self::$raffle_list)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 范围
|
||||||
|
if ($day <= 2 && empty($raffle['update_time'])) {
|
||||||
|
$info = $raffle['gift_name'] . 'x' . $raffle['gift_num'];
|
||||||
|
Log::notice("实物奖励于" . $raffle['end_time'] . "获奖: {$info} ,请留意查看...");
|
||||||
|
Notice::push('raffle', $info);
|
||||||
|
}
|
||||||
|
array_push(self::$raffle_list, $raffle['id']);
|
||||||
|
}
|
||||||
|
self::$raffle_lock = time() + 6 * 60 * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取活动礼物中奖纪录
|
||||||
|
*/
|
||||||
|
private static function giftAward()
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'type' => 'type',
|
||||||
|
'raffleId' => 'raffle_id'
|
||||||
|
];
|
||||||
|
// Web V3 Notice
|
||||||
|
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v3/smalltv/Notice';
|
||||||
|
// 请求 && 解码
|
||||||
|
$raw = Curl::get($url, Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,15 +8,19 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
class Danmu
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class Barrage
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time() || getenv('USE_DANMU') == 'false') {
|
if (self::getLock() > time() || getenv('USE_DANMU') == 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$room_id = empty(getenv('DANMU_ROOMID')) ? Live::getUserRecommend() : Live::getRealRoomID(getenv('DANMU_ROOMID'));
|
$room_id = empty(getenv('DANMU_ROOMID')) ? Live::getUserRecommend() : Live::getRealRoomID(getenv('DANMU_ROOMID'));
|
||||||
@ -28,14 +32,18 @@ class Danmu
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (self::privateSendMsg($info)) {
|
if (self::privateSendMsg($info)) {
|
||||||
self::$lock = time() + 3600;
|
self::setLock(3600);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$lock = time() + 30;
|
self::setLock(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取随机弹幕
|
|
||||||
|
/**
|
||||||
|
* @use 获取随机弹幕
|
||||||
|
* @return \Exception|false|mixed|string
|
||||||
|
*/
|
||||||
private static function getMsgInfo()
|
private static function getMsgInfo()
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -80,7 +88,11 @@ class Danmu
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//发送弹幕通用模块
|
/**
|
||||||
|
* @use 弹幕通用模块
|
||||||
|
* @param $info
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
private static function sendMsg($info)
|
private static function sendMsg($info)
|
||||||
{
|
{
|
||||||
$user_info = User::parseCookies();
|
$user_info = User::parseCookies();
|
||||||
@ -101,24 +113,26 @@ class Danmu
|
|||||||
return Curl::post('https://api.live.bilibili.com/msg/send', Sign::api($payload));
|
return Curl::post('https://api.live.bilibili.com/msg/send', Sign::api($payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
//使用发送弹幕模块
|
/**
|
||||||
|
* @use 发送弹幕模块
|
||||||
|
* @param $info
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private static function privateSendMsg($info)
|
private static function privateSendMsg($info)
|
||||||
{
|
{
|
||||||
//TODO 暂时性功能 有需求就修改
|
//TODO 暂时性功能 有需求就修改
|
||||||
$raw = self::sendMsg($info);
|
$raw = self::sendMsg($info);
|
||||||
$de_raw = json_decode($raw, true);
|
$de_raw = json_decode($raw, true);
|
||||||
|
|
||||||
if ($de_raw['code'] == 1001) {
|
if ($de_raw['code'] == 1001) {
|
||||||
Log::warning($de_raw['msg']);
|
Log::warning($de_raw['msg']);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$de_raw['code']) {
|
if (!$de_raw['code']) {
|
||||||
Log::info('弹幕发送成功!');
|
Log::info('活跃弹幕发送成功!');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Log::error("活跃弹幕发送失败!, {$de_raw['msg']}");
|
||||||
|
|
||||||
Log::error("弹幕发送失败, {$de_raw['msg']}");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,16 +9,16 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
|
||||||
abstract class BaseRaffle
|
abstract class BaseRaffle
|
||||||
{
|
{
|
||||||
const ACTIVE_TITLE = '';
|
const ACTIVE_TITLE = '';
|
||||||
const ACTIVE_SWITCH = '';
|
const ACTIVE_SWITCH = '';
|
||||||
|
|
||||||
public static $lock;
|
|
||||||
public static $rw_lock;
|
|
||||||
|
|
||||||
protected static $wait_list;
|
protected static $wait_list;
|
||||||
protected static $finish_list;
|
protected static $finish_list;
|
||||||
protected static $all_list;
|
protected static $all_list;
|
||||||
@ -28,29 +28,34 @@ abstract class BaseRaffle
|
|||||||
if (getenv(static::ACTIVE_SWITCH) == 'false') {
|
if (getenv(static::ACTIVE_SWITCH) == 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (static::$lock > time()) {
|
if (static::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static::startLottery();
|
static::startLottery();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 抽奖逻辑
|
* @use 抽奖逻辑
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected static function startLottery(): bool
|
protected static function startLottery(): bool
|
||||||
{
|
{
|
||||||
$max_num = mt_rand(10, 20);
|
|
||||||
if (count(static::$wait_list) == 0) {
|
if (count(static::$wait_list) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (count(static::$wait_list) < 100) {
|
||||||
|
$max_num = mt_rand(10, 20);
|
||||||
|
} else {
|
||||||
|
$max_num = mt_rand(45, 90);
|
||||||
|
}
|
||||||
static::$wait_list = static::arrKeySort(static::$wait_list, 'wait');
|
static::$wait_list = static::arrKeySort(static::$wait_list, 'wait');
|
||||||
for ($i = 0; $i <= $max_num; $i++) {
|
for ($i = 0; $i <= $max_num; $i++) {
|
||||||
$raffle = array_shift(static::$wait_list);
|
$raffle = array_shift(static::$wait_list);
|
||||||
if (is_null($raffle)) {
|
if (is_null($raffle)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ($raffle['wait'] > strtotime(date("Y-m-d H:i:s"))) {
|
if ($raffle['wait'] > time()) {
|
||||||
array_push(static::$wait_list, $raffle);
|
array_push(static::$wait_list, $raffle);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -61,13 +66,34 @@ abstract class BaseRaffle
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 返回抽奖数据
|
||||||
|
* @param int $room_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected static function check(int $room_id): array
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'roomid' => $room_id
|
||||||
|
];
|
||||||
|
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v1/lottery/getLotteryInfo';
|
||||||
|
$raw = Curl::get($url, Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
if (!isset($de_raw['data']) || $de_raw['code']) {
|
||||||
|
Log::error("获取抽奖数据错误,{$de_raw['message']}");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return $de_raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查抽奖列表
|
* @use 解析抽奖数据
|
||||||
* @param $rid
|
* @param int $room_id
|
||||||
|
* @param array $data
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
abstract protected static function check($rid): bool;
|
abstract protected static function parse(int $room_id, array $data): bool;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,12 +126,13 @@ abstract class BaseRaffle
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重复检测
|
* @use 去重检测
|
||||||
* @param int $lid
|
* @param $lid
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected static function toRepeatLid(int $lid): bool
|
protected static function toRepeatLid($lid): bool
|
||||||
{
|
{
|
||||||
|
$lid = (int)$lid;
|
||||||
if (in_array($lid, static::$all_list)) {
|
if (in_array($lid, static::$all_list)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -113,12 +140,11 @@ abstract class BaseRaffle
|
|||||||
static::$all_list = [];
|
static::$all_list = [];
|
||||||
}
|
}
|
||||||
array_push(static::$all_list, $lid);
|
array_push(static::$all_list, $lid);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据推入队列
|
* @use 数据推入队列
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@ -131,9 +157,12 @@ abstract class BaseRaffle
|
|||||||
if (Live::fishingDetection($data['rid'])) {
|
if (Live::fishingDetection($data['rid'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static::check($data['rid']);
|
$raffles_info = static::check($data['rid']);
|
||||||
|
if (!empty($raffles_info)) {
|
||||||
|
static::parse($data['rid'], $raffles_info);
|
||||||
|
}
|
||||||
$wait_num = count(static::$wait_list);
|
$wait_num = count(static::$wait_list);
|
||||||
if ($wait_num > 2) {
|
if ($wait_num > 4 && ($wait_num % 2)) {
|
||||||
Log::info("当前队列中共有 {$wait_num} 个" . static::ACTIVE_TITLE . "待抽奖");
|
Log::info("当前队列中共有 {$wait_num} 个" . static::ACTIVE_TITLE . "待抽奖");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -8,23 +8,29 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class Daily
|
class Daily
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self::dailyBag();
|
self::dailyBag();
|
||||||
|
self::setLock( 8 * 60 * 60);
|
||||||
self::$lock = time() + 3600;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function dailyBag()
|
/**
|
||||||
|
* @use 领取每日包裹
|
||||||
|
*/
|
||||||
|
private static function dailyBag()
|
||||||
{
|
{
|
||||||
$payload = [];
|
$payload = [];
|
||||||
$data = Curl::get('https://api.live.bilibili.com/gift/v2/live/receive_daily_bag', Sign::api($payload));
|
$data = Curl::get('https://api.live.bilibili.com/gift/v2/live/receive_daily_bag', Sign::api($payload));
|
||||||
@ -8,12 +8,17 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class DataTreating
|
class DataTreating
|
||||||
{
|
{
|
||||||
|
// TODO 独立分发 Push||Pull数据
|
||||||
/**
|
/**
|
||||||
* @desc 抽奖分发
|
* @use 抽奖分发
|
||||||
* @param array $data
|
* @param array $data
|
||||||
*/
|
*/
|
||||||
public static function distribute(array $data)
|
public static function distribute(array $data)
|
||||||
@ -28,19 +33,19 @@ class DataTreating
|
|||||||
switch ($data['raffle_type']) {
|
switch ($data['raffle_type']) {
|
||||||
case "storm":
|
case "storm":
|
||||||
// 风暴
|
// 风暴
|
||||||
Storm::pushToQueue($info);
|
StormRaffle::pushToQueue($info);
|
||||||
break;
|
break;
|
||||||
case "raffle":
|
case "raffle":
|
||||||
// 礼物
|
// 礼物
|
||||||
UnifyRaffle::pushToQueue($info);
|
GiftRaffle::pushToQueue($info);
|
||||||
break;
|
break;
|
||||||
case "guard":
|
case "guard":
|
||||||
// 舰长
|
// 舰长
|
||||||
Guard::pushToQueue($info);
|
GuardRaffle::pushToQueue($info);
|
||||||
break;
|
break;
|
||||||
case "small_tv":
|
case "small_tv":
|
||||||
// 电视
|
// 电视
|
||||||
UnifyRaffle::pushToQueue($info);
|
GiftRaffle::pushToQueue($info);
|
||||||
break;
|
break;
|
||||||
case 'pk':
|
case 'pk':
|
||||||
// 乱斗
|
// 乱斗
|
||||||
@ -48,7 +53,7 @@ class DataTreating
|
|||||||
break;
|
break;
|
||||||
case 'anchor':
|
case 'anchor':
|
||||||
// 天选时刻
|
// 天选时刻
|
||||||
Anchor::pushToQueue($info);
|
AnchorRaffle::pushToQueue($info);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -8,27 +8,34 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class GiftHeart
|
class GiftHeart
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
// RUN
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (self::giftheart()) {
|
if (self::giftHeart()) {
|
||||||
self::$lock = time() + 60 * 60;
|
self::setLock(60 * 60);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self::$lock = time() + 5 * 60;
|
self::setLock(5 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GIFT HEART
|
|
||||||
protected static function giftheart(): bool
|
/**
|
||||||
|
* @use 礼物心跳
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function giftHeart(): bool
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
'roomid' => getenv('ROOM_ID'),
|
'roomid' => getenv('ROOM_ID'),
|
||||||
102
src/plugin/GiftRaffle.php
Normal file
102
src/plugin/GiftRaffle.php
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class GiftRaffle extends BaseRaffle
|
||||||
|
{
|
||||||
|
const ACTIVE_TITLE = '活动礼物';
|
||||||
|
const ACTIVE_SWITCH = 'USE_ACTIVE';
|
||||||
|
|
||||||
|
use TimeLock;
|
||||||
|
|
||||||
|
protected static $wait_list = [];
|
||||||
|
protected static $finish_list = [];
|
||||||
|
protected static $all_list = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 解析数据
|
||||||
|
* @param int $room_id
|
||||||
|
* @param array $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function parse(int $room_id, array $data): bool
|
||||||
|
{
|
||||||
|
// 防止异常
|
||||||
|
if (!array_key_exists('gift_list', $data['data'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$de_raw = $data['data']['gift_list'];
|
||||||
|
if (empty($de_raw)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($de_raw as $gift) {
|
||||||
|
// 无效抽奖
|
||||||
|
if ($gift['status'] != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 去重
|
||||||
|
if (self::toRepeatLid($gift['raffleId'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$data = [
|
||||||
|
'room_id' => $room_id,
|
||||||
|
'raffle_id' => $gift['raffleId'],
|
||||||
|
'title' => $gift['title'],
|
||||||
|
'type' => $gift['type'],
|
||||||
|
'wait' => $gift['time_wait'] + time(),
|
||||||
|
];
|
||||||
|
Statistics::addPushList(self::ACTIVE_TITLE);
|
||||||
|
array_push(self::$wait_list, $data);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 请求抽奖
|
||||||
|
* @param array $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function lottery(array $data): bool
|
||||||
|
{
|
||||||
|
$user_info = User::parseCookies();
|
||||||
|
$payload = [
|
||||||
|
'raffleId' => $data['raffle_id'],
|
||||||
|
'roomid' => $data['room_id'],
|
||||||
|
'type' => $data['type'],
|
||||||
|
'csrf_token' => $user_info['token'],
|
||||||
|
'csrf' => $user_info['token'],
|
||||||
|
'visit_id' => null,
|
||||||
|
];
|
||||||
|
// V3接口 暂做保留处理
|
||||||
|
// $url = 'https://api.live.bilibili.com/gift/v3/smalltv/join';
|
||||||
|
// $url = 'https://api.live.bilibili.com/xlive/lottery-interface/v5/smalltv/Join';
|
||||||
|
$url = 'https://api.live.bilibili.com/gift/v4/smalltv/getAward';
|
||||||
|
$raw = Curl::post($url, Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
if (isset($de_raw['code']) && !$de_raw['code']) {
|
||||||
|
// 推送中奖信息
|
||||||
|
if ($de_raw['data']['gift_name'] != '辣条' && $de_raw['data']['gift_name'] != '') {
|
||||||
|
$info = $de_raw['data']['gift_name'] . 'x' . $de_raw['data']['gift_num'];
|
||||||
|
Notice::push('gift', $info);
|
||||||
|
}
|
||||||
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['data']['gift_name']}x{$de_raw['data']['gift_num']}");
|
||||||
|
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
||||||
|
} else {
|
||||||
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['msg']}");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
275
src/plugin/GiftSend.php
Normal file
275
src/plugin/GiftSend.php
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class GiftSend
|
||||||
|
{
|
||||||
|
use TimeLock;
|
||||||
|
protected static $uid = 0;
|
||||||
|
protected static $tid = 0;
|
||||||
|
protected static $r_uid = 0;
|
||||||
|
protected static $room_id = 0;
|
||||||
|
protected static $room_list = [];
|
||||||
|
protected static $medal_list = [];
|
||||||
|
|
||||||
|
|
||||||
|
public static function run()
|
||||||
|
{
|
||||||
|
if (self::getLock() > time()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!self::$uid) {
|
||||||
|
self::getUserInfo();
|
||||||
|
}
|
||||||
|
// 方案一未通过使用方案2
|
||||||
|
if (!self::procOne()) {
|
||||||
|
self::procTwo();
|
||||||
|
}
|
||||||
|
self::$room_list = [];
|
||||||
|
self::$medal_list = [];
|
||||||
|
self::$tid = 0;
|
||||||
|
self::setLock(5 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 方案1
|
||||||
|
*/
|
||||||
|
protected static function procOne()
|
||||||
|
{
|
||||||
|
if (!self::setTargetList()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self::getMedalList();
|
||||||
|
foreach (self::$medal_list as $key => $val) {
|
||||||
|
$bag_list = self::fetchBagList();
|
||||||
|
array_multisort(array_column($bag_list, "expire_at"), SORT_ASC, $bag_list);
|
||||||
|
if (getenv('FEED_FILL') == 'false') {
|
||||||
|
$bag_list = self::checkExpireGift($bag_list);
|
||||||
|
}
|
||||||
|
if (count($bag_list)) {
|
||||||
|
self::$tid = $key;
|
||||||
|
self::getRoomInfo();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
foreach ($bag_list as $gift) {
|
||||||
|
// 是辣条、亿元 && 不是过期礼物
|
||||||
|
if (!in_array($gift['gift_id'], [1, 6]) && getenv('FEED_FILL') != 'false') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$amt = self::calcAmt($gift);
|
||||||
|
self::sendGift($gift, $amt);
|
||||||
|
$val -= $amt;
|
||||||
|
if (!$val) {
|
||||||
|
Log::notice("直播间 {$key} 亲密度 {$val} 送满啦~送满啦~");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!count(self::$medal_list)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 方案2
|
||||||
|
*/
|
||||||
|
protected static function procTwo()
|
||||||
|
{
|
||||||
|
$bag_list = self::fetchBagList();
|
||||||
|
$expire_gift = self::checkExpireGift($bag_list);
|
||||||
|
if (count($expire_gift)) {
|
||||||
|
self::getRoomInfo();
|
||||||
|
foreach ($expire_gift as $gift) {
|
||||||
|
self::sendGift($gift, $gift['gift_num']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 设置房间列表
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function setTargetList(): bool
|
||||||
|
{
|
||||||
|
$temp = empty(getenv('ROOM_LIST')) ? null : getenv('ROOM_LIST');
|
||||||
|
if (is_null($temp)) return false;
|
||||||
|
self::$room_list = explode(',', getenv('ROOM_LIST'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取背包列表
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected static function fetchBagList(): array
|
||||||
|
{
|
||||||
|
$bag_list = [];
|
||||||
|
$payload = [];
|
||||||
|
$data = Curl::get('https://api.live.bilibili.com/gift/v2/gift/bag_list', Sign::api($payload));
|
||||||
|
$data = json_decode($data, true);
|
||||||
|
if (isset($data['code']) && $data['code']) {
|
||||||
|
Log::warning('背包查看失败!', ['msg' => $data['message']]);
|
||||||
|
return $bag_list;
|
||||||
|
}
|
||||||
|
if (isset($data['data']['list'])) {
|
||||||
|
$bag_list = $data['data']['list'];
|
||||||
|
array_multisort(array_column($bag_list, "gift_id"), SORT_DESC, $bag_list);
|
||||||
|
foreach ($bag_list as $vo) {
|
||||||
|
// 去除永久礼物
|
||||||
|
if ($vo['corner_mark'] == '永久') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
array_push($bag_list, $vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $bag_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 查找过期礼物
|
||||||
|
* @param array $bag_list
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected static function checkExpireGift(array $bag_list): array
|
||||||
|
{
|
||||||
|
$expire_gift_list = [];
|
||||||
|
foreach ($bag_list as $gift) {
|
||||||
|
if ($gift['expire_at'] >= time() && $gift['expire_at'] <= time() + 3600) {
|
||||||
|
array_push($expire_gift_list, $gift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $expire_gift_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取勋章列表(过滤无勋章或已满)
|
||||||
|
*/
|
||||||
|
protected static function getMedalList()
|
||||||
|
{
|
||||||
|
self::$medal_list = [];
|
||||||
|
Log::info('正在获取勋章列表...');
|
||||||
|
$payload = [];
|
||||||
|
$data = Curl::get('https://api.live.bilibili.com/i/api/medal?page=1&pageSize=25', Sign::api($payload));
|
||||||
|
$data = json_decode($data, true);
|
||||||
|
if (isset($data['code']) && $data['code']) {
|
||||||
|
Log::warning('获取勋章列表失败!', ['msg' => $data['message']]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log::info('勋章列表获取成功!');
|
||||||
|
if (isset($data['data']['fansMedalList'])) {
|
||||||
|
foreach ($data['data']['fansMedalList'] as $vo) {
|
||||||
|
if (in_array($vo['roomid'], self::$room_list) && ($vo['day_limit'] - $vo['today_feed'])) {
|
||||||
|
self::$medal_list[(string)$vo['roomid']] = ($vo['day_limit'] - $vo['today_feed']);
|
||||||
|
// $data = [
|
||||||
|
// $vo['roomid'] => ($vo['day_limit'] - $vo['today_feed'])
|
||||||
|
// ];
|
||||||
|
// array_push(self::$medal_list, $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取UID
|
||||||
|
*/
|
||||||
|
protected static function getUserInfo()
|
||||||
|
{
|
||||||
|
$payload = [];
|
||||||
|
$data = Curl::get('https://api.live.bilibili.com/xlive/web-ucenter/user/get_user_info', Sign::api($payload));
|
||||||
|
$data = json_decode($data, true);
|
||||||
|
if (isset($data['code']) && $data['code']) {
|
||||||
|
Log::warning('获取帐号信息失败!', ['msg' => $data['message']]);
|
||||||
|
Log::warning('清空礼物功能禁用!');
|
||||||
|
self::$lock = time() + 100000000;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self::$uid = $data['data']['uid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取直播间信息
|
||||||
|
*/
|
||||||
|
protected static function getRoomInfo()
|
||||||
|
{
|
||||||
|
Log::info('正在生成直播间信息...');
|
||||||
|
$payload = [
|
||||||
|
'id' => empty(self::$tid) ? getenv('ROOM_ID') : self::$tid,
|
||||||
|
];
|
||||||
|
$data = Curl::get('https://api.live.bilibili.com/room/v1/Room/room_init', Sign::api($payload));
|
||||||
|
$data = json_decode($data, true);
|
||||||
|
if (isset($data['code']) && $data['code']) {
|
||||||
|
Log::warning('获取主播房间号失败!', ['msg' => $data['message']]);
|
||||||
|
Log::warning('清空礼物功能禁用!');
|
||||||
|
self::$lock = time() + 100000000;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log::info('直播间信息生成完毕!');
|
||||||
|
self::$r_uid = (string)$data['data']['uid'];
|
||||||
|
self::$room_id = (string)$data['data']['room_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 计算赠送数量
|
||||||
|
* @param array $gift
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected static function calcAmt(array $gift): int
|
||||||
|
{
|
||||||
|
$amt = $gift['gift_num'];
|
||||||
|
if ($gift['gift_id'] == 1) {
|
||||||
|
$amt = (self::$medal_list[self::$room_id] > $gift['gift_num']) ? $gift['gift_num'] : self::$medal_list[self::$room_id];
|
||||||
|
}
|
||||||
|
if ($gift['gift_id'] == 6) {
|
||||||
|
$amt = (floor(self::$medal_list[self::$room_id] / 10) > $gift['gift_num']) ? $gift['gift_num'] : floor(self::$medal_list[self::$room_id] / 10);
|
||||||
|
}
|
||||||
|
return $amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 赠送礼物
|
||||||
|
* @param array $value
|
||||||
|
* @param int $amt
|
||||||
|
*/
|
||||||
|
protected static function sendGift(array $value, int $amt)
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'coin_type' => 'silver',
|
||||||
|
'gift_id' => $value['gift_id'],
|
||||||
|
'ruid' => self::$r_uid,
|
||||||
|
'uid' => self::$uid,
|
||||||
|
'biz_id' => self::$room_id,
|
||||||
|
'gift_num' => $amt,
|
||||||
|
'data_source_id' => '',
|
||||||
|
'data_behavior_id' => '',
|
||||||
|
'bag_id' => $value['bag_id']
|
||||||
|
];
|
||||||
|
$data = Curl::post('https://api.live.bilibili.com/gift/v2/live/bag_send', Sign::api($payload));
|
||||||
|
$data = json_decode($data, true);
|
||||||
|
if (isset($data['code']) && $data['code']) {
|
||||||
|
Log::warning('送礼失败!', ['msg' => $data['message']]);
|
||||||
|
} else {
|
||||||
|
Log::notice("成功向 {$payload['biz_id']} 投喂了 {$amt} 个{$value['gift_name']}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,22 +8,25 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class GroupSignIn
|
class GroupSignIn
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
// RUN
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$groups = self::getGroupList();
|
$groups = self::getGroupList();
|
||||||
if (empty($groups)) {
|
if (empty($groups)) {
|
||||||
self::$lock = time() + 24 * 60 * 60;
|
self::setLock(24 * 60 * 60);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,10 +34,14 @@ class GroupSignIn
|
|||||||
self::signInGroup($group);
|
self::signInGroup($group);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$lock = time() + 8 * 60 * 60;
|
self::setLock(8 * 60 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
//GROUP LIST
|
|
||||||
|
/**
|
||||||
|
* @use 获取友爱社列表
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
protected static function getGroupList(): array
|
protected static function getGroupList(): array
|
||||||
{
|
{
|
||||||
$payload = [];
|
$payload = [];
|
||||||
@ -48,7 +55,12 @@ class GroupSignIn
|
|||||||
return $de_raw['data']['list'];
|
return $de_raw['data']['list'];
|
||||||
}
|
}
|
||||||
|
|
||||||
//SIGN IN
|
|
||||||
|
/**
|
||||||
|
* @use 签到
|
||||||
|
* @param array $groupInfo
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected static function signInGroup(array $groupInfo): bool
|
protected static function signInGroup(array $groupInfo): bool
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
113
src/plugin/GuardRaffle.php
Normal file
113
src/plugin/GuardRaffle.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class GuardRaffle extends BaseRaffle
|
||||||
|
{
|
||||||
|
const ACTIVE_TITLE = '总督舰长';
|
||||||
|
const ACTIVE_SWITCH = 'USE_GUARD';
|
||||||
|
|
||||||
|
use TimeLock;
|
||||||
|
|
||||||
|
protected static $wait_list = [];
|
||||||
|
protected static $finish_list = [];
|
||||||
|
protected static $all_list = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 解析数据
|
||||||
|
* @param int $room_id
|
||||||
|
* @param array $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function parse(int $room_id, array $data): bool
|
||||||
|
{
|
||||||
|
// 防止异常
|
||||||
|
if (!array_key_exists('guard', $data['data'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$de_raw = $data['data']['guard'];
|
||||||
|
if (empty($de_raw)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($de_raw as $guard) {
|
||||||
|
// 无效抽奖
|
||||||
|
if ($guard['status'] != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 去重
|
||||||
|
if (self::toRepeatLid($guard['id'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 获取等级名称
|
||||||
|
switch ($guard['privilege_type']) {
|
||||||
|
case 1:
|
||||||
|
$raffle_name = '总督';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
$raffle_name = '提督';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
$raffle_name = '舰长';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$raffle_name = '舰队';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 推入列表
|
||||||
|
$data = [
|
||||||
|
'room_id' => $room_id,
|
||||||
|
'raffle_id' => $guard['id'],
|
||||||
|
'raffle_name' => $raffle_name,
|
||||||
|
'wait' => time()
|
||||||
|
];
|
||||||
|
Statistics::addPushList(self::ACTIVE_TITLE);
|
||||||
|
array_push(self::$wait_list, $data);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 请求抽奖
|
||||||
|
* @param array $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function lottery(array $data): bool
|
||||||
|
{
|
||||||
|
$user_info = User::parseCookies();
|
||||||
|
$payload = [
|
||||||
|
'id' => $data['raffle_id'],
|
||||||
|
'roomid' => $data['room_id'],
|
||||||
|
"type" => "guard",
|
||||||
|
'csrf_token' => $user_info['token'],
|
||||||
|
'csrf' => $user_info['token']
|
||||||
|
];
|
||||||
|
$url = 'https://api.live.bilibili.com/lottery/v2/lottery/join';
|
||||||
|
$raw = Curl::post($url, Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
|
||||||
|
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
|
||||||
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['data']['message']}");
|
||||||
|
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
||||||
|
} else {
|
||||||
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['msg']}");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -8,24 +8,31 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class Heart
|
class Heart
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self::pc();
|
self::pc();
|
||||||
self::mobile();
|
self::mobile();
|
||||||
|
|
||||||
self::$lock = time() + 300;
|
self::setLock(5 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use pc端心跳
|
||||||
|
*/
|
||||||
protected static function pc()
|
protected static function pc()
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
@ -41,6 +48,9 @@ class Heart
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 手机端心跳
|
||||||
|
*/
|
||||||
protected static function mobile()
|
protected static function mobile()
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
173
src/plugin/Live.php
Normal file
173
src/plugin/Live.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class Live
|
||||||
|
{
|
||||||
|
use TimeLock;
|
||||||
|
|
||||||
|
|
||||||
|
public static function run()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取分区列表
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function fetchLiveAreas(): array
|
||||||
|
{
|
||||||
|
$areas = [];
|
||||||
|
$url = "http://api.live.bilibili.com/room/v1/Area/getList";
|
||||||
|
$raw = Curl::get($url);
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
// 防止异常
|
||||||
|
if (!isset($de_raw['data']) || $de_raw['code']) {
|
||||||
|
Log::warning("获取直播分区异常: " . $de_raw['msg']);
|
||||||
|
$areas = range(1, 6);
|
||||||
|
} else {
|
||||||
|
foreach ($de_raw['data'] as $area) {
|
||||||
|
array_push($areas, $area['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $areas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use AREA_ID转ROOM_ID
|
||||||
|
* @param $area_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function areaToRid($area_id): array
|
||||||
|
{
|
||||||
|
$url = "https://api.live.bilibili.com/room/v1/area/getRoomList?platform=web&parent_area_id={$area_id}&cate_id=0&area_id=0&sort_type=online&page=1&page_size=30";
|
||||||
|
$raw = Curl::get($url);
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
// 防止异常
|
||||||
|
if (!isset($de_raw['data']) || $de_raw['code']) {
|
||||||
|
Log::warning("获取直播分区异常: " . $de_raw['msg']);
|
||||||
|
$area_info = [
|
||||||
|
'area_id' => $area_id,
|
||||||
|
'room_id' => 23058
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$area_info = [
|
||||||
|
'area_id' => $area_id,
|
||||||
|
'room_id' => $de_raw['data'][0]['roomid']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $area_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取随机直播房间号
|
||||||
|
* @return int
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function getUserRecommend()
|
||||||
|
{
|
||||||
|
$raw = Curl::get('https://api.live.bilibili.com/room/v1/Area/getListByAreaID?areaId=0&sort=online&pageSize=30&page=1');
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
if ($de_raw['code'] != '0') {
|
||||||
|
return 23058;
|
||||||
|
}
|
||||||
|
return $de_raw['data'][random_int(1, 29)]['roomid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取直播房间号
|
||||||
|
* @param $room_id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function getRealRoomID($room_id)
|
||||||
|
{
|
||||||
|
$raw = Curl::get('https://api.live.bilibili.com/room/v1/Room/room_init?id=' . $room_id);
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
if ($de_raw['code']) {
|
||||||
|
Log::warning($room_id . ' : ' . $de_raw['msg']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($de_raw['data']['is_hidden']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($de_raw['data']['is_locked']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($de_raw['data']['encrypted']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $de_raw['data']['room_id'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 钓鱼检测
|
||||||
|
* @param $room_id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function fishingDetection($room_id): bool
|
||||||
|
{
|
||||||
|
if (self::getRealRoomID($room_id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 随机延迟
|
||||||
|
* @param int $min
|
||||||
|
* @param int $max
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function randDelay($min = 0, $max = 3): bool
|
||||||
|
{
|
||||||
|
$rand = $min + mt_rand() / mt_getrandmax() * ($max - $min);
|
||||||
|
sleep($rand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 访问直播间
|
||||||
|
* @param $room_id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function goToRoom($room_id): bool
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'room_id' => $room_id,
|
||||||
|
];
|
||||||
|
// Log::info('进入直播间[' . $room_id . ']抽奖!');
|
||||||
|
Curl::post('https://api.live.bilibili.com/room/v1/Room/room_entry_action', Sign::api($payload));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取毫秒
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public static function getMillisecond()
|
||||||
|
{
|
||||||
|
list($t1, $t2) = explode(' ', microtime());
|
||||||
|
return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -7,21 +7,29 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
use BiliHelper\Core\Config;
|
||||||
|
|
||||||
|
|
||||||
class Login
|
class Login
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
|
if (self::getLock()) {
|
||||||
|
self::check();
|
||||||
|
return;
|
||||||
|
}
|
||||||
Log::info('开始启动程序...');
|
Log::info('开始启动程序...');
|
||||||
if (getenv('ACCESS_TOKEN') == "") {
|
if (getenv('ACCESS_TOKEN') == "") {
|
||||||
Log::info('令牌载入中...');
|
Log::info('令牌载入中...');
|
||||||
self::login();
|
self::login();
|
||||||
}
|
}
|
||||||
// 重载配置文件
|
|
||||||
Index::$dotenv->overload();
|
|
||||||
|
|
||||||
Log::info('正在检查令牌合法性...');
|
Log::info('正在检查令牌合法性...');
|
||||||
if (!self::info()) {
|
if (!self::info()) {
|
||||||
@ -32,15 +40,19 @@ class Login
|
|||||||
self::login();
|
self::login();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self::$lock = time() + 3600;
|
self::setLock(3600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 检查令牌
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function check()
|
public static function check()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
self::$lock = time() + 7200;
|
self::setLock(7200);
|
||||||
if (!self::info()) {
|
if (!self::info()) {
|
||||||
Log::warning('令牌即将过期');
|
Log::warning('令牌即将过期');
|
||||||
Log::info('申请更换令牌中...');
|
Log::info('申请更换令牌中...');
|
||||||
@ -53,6 +65,10 @@ class Login
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取令牌信息
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected static function info()
|
protected static function info()
|
||||||
{
|
{
|
||||||
$access_token = getenv('ACCESS_TOKEN');
|
$access_token = getenv('ACCESS_TOKEN');
|
||||||
@ -69,6 +85,10 @@ class Login
|
|||||||
return $data['data']['expires_in'] > 14400;
|
return $data['data']['expires_in'] > 14400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 刷新token
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function refresh()
|
public static function refresh()
|
||||||
{
|
{
|
||||||
$access_token = getenv('ACCESS_TOKEN');
|
$access_token = getenv('ACCESS_TOKEN');
|
||||||
@ -85,14 +105,19 @@ class Login
|
|||||||
}
|
}
|
||||||
Log::info('令牌生成完毕!');
|
Log::info('令牌生成完毕!');
|
||||||
$access_token = $data['data']['access_token'];
|
$access_token = $data['data']['access_token'];
|
||||||
File::writeNewEnvironmentFileWith('ACCESS_TOKEN', $access_token);
|
Config::put('ACCESS_TOKEN', $access_token);
|
||||||
Log::info(' > access token: ' . $access_token);
|
Log::info(' > access token: ' . $access_token);
|
||||||
$refresh_token = $data['data']['refresh_token'];
|
$refresh_token = $data['data']['refresh_token'];
|
||||||
File::writeNewEnvironmentFileWith('REFRESH_TOKEN', $refresh_token);
|
Config::put('REFRESH_TOKEN', $refresh_token);
|
||||||
Log::info(' > refresh token: ' . $refresh_token);
|
Log::info(' > refresh token: ' . $refresh_token);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 普通登陆
|
||||||
|
* @param string $captcha
|
||||||
|
* @param array $headers
|
||||||
|
*/
|
||||||
protected static function login($captcha = '', $headers = [])
|
protected static function login($captcha = '', $headers = [])
|
||||||
{
|
{
|
||||||
$user = getenv('APP_USER');
|
$user = getenv('APP_USER');
|
||||||
@ -129,7 +154,7 @@ class Login
|
|||||||
$data = Curl::post('https://passport.bilibili.com/api/v2/oauth2/login', Sign::api($payload), $headers);
|
$data = Curl::post('https://passport.bilibili.com/api/v2/oauth2/login', Sign::api($payload), $headers);
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
if (isset($data['code']) && $data['code'] == -105) {
|
if (isset($data['code']) && $data['code'] == -105) {
|
||||||
$captcha_data = static::loginWithCaptcha();
|
$captcha_data = self::loginWithCaptcha();
|
||||||
$captcha = $captcha_data['captcha'];
|
$captcha = $captcha_data['captcha'];
|
||||||
$headers = $captcha_data['headers'];
|
$headers = $captcha_data['headers'];
|
||||||
continue;
|
continue;
|
||||||
@ -148,16 +173,20 @@ class Login
|
|||||||
self::saveCookie($data);
|
self::saveCookie($data);
|
||||||
Log::info('令牌获取成功!');
|
Log::info('令牌获取成功!');
|
||||||
$access_token = $data['data']['token_info']['access_token'];
|
$access_token = $data['data']['token_info']['access_token'];
|
||||||
File::writeNewEnvironmentFileWith('ACCESS_TOKEN', $access_token);
|
Config::put('ACCESS_TOKEN', $access_token);
|
||||||
Log::info(' > access token: ' . $access_token);
|
Log::info(' > access token: ' . $access_token);
|
||||||
$refresh_token = $data['data']['token_info']['refresh_token'];
|
$refresh_token = $data['data']['token_info']['refresh_token'];
|
||||||
File::writeNewEnvironmentFileWith('REFRESH_TOKEN', $refresh_token);
|
Config::put('REFRESH_TOKEN', $refresh_token);
|
||||||
Log::info(' > refresh token: ' . $refresh_token);
|
Log::info(' > refresh token: ' . $refresh_token);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 验证码登陆
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
protected static function loginWithCaptcha()
|
protected static function loginWithCaptcha()
|
||||||
{
|
{
|
||||||
Log::info('登录需要验证, 启动验证码登录!');
|
Log::info('登录需要验证, 启动验证码登录!');
|
||||||
@ -169,7 +198,7 @@ class Login
|
|||||||
];
|
];
|
||||||
$data = Curl::other('https://passport.bilibili.com/captcha', null, $headers);
|
$data = Curl::other('https://passport.bilibili.com/captcha', null, $headers);
|
||||||
$data = base64_encode($data);
|
$data = base64_encode($data);
|
||||||
$captcha = static::ocrCaptcha($data);
|
$captcha = self::ocrCaptcha($data);
|
||||||
return [
|
return [
|
||||||
'captcha' => $captcha,
|
'captcha' => $captcha,
|
||||||
'headers' => $headers,
|
'headers' => $headers,
|
||||||
@ -177,6 +206,11 @@ class Login
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 识别验证码
|
||||||
|
* @param $captcha_img
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
private static function ocrCaptcha($captcha_img)
|
private static function ocrCaptcha($captcha_img)
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
@ -192,6 +226,10 @@ class Login
|
|||||||
return $de_raw['message'];
|
return $de_raw['message'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 保存cookie
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
private static function saveCookie($data)
|
private static function saveCookie($data)
|
||||||
{
|
{
|
||||||
Log::info('COOKIE获取成功!');
|
Log::info('COOKIE获取成功!');
|
||||||
@ -201,7 +239,7 @@ class Login
|
|||||||
foreach ($cookies as $cookie) {
|
foreach ($cookies as $cookie) {
|
||||||
$temp .= $cookie['name'] . '=' . $cookie['value'] . ';';
|
$temp .= $cookie['name'] . '=' . $cookie['value'] . ';';
|
||||||
}
|
}
|
||||||
File::writeNewEnvironmentFileWith('COOKIE', $temp);
|
Config::put('COOKIE', $temp);
|
||||||
Log::info(' > auth cookie: ' . $temp);
|
Log::info(' > auth cookie: ' . $temp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -8,25 +8,34 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class MasterSite
|
class MasterSite
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time() || getenv('USE_MASTER_SITE') == 'false') {
|
if (self::getLock() > time() || getenv('USE_MASTER_SITE') == 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (self::watchAid() && self::shareAid() && self::coinAdd()) {
|
if (self::watchAid() && self::shareAid() && self::coinAdd()) {
|
||||||
self::$lock = time() + 24 * 60 * 60;
|
self::setLock( 24 * 60 * 60);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self::$lock = time() + 3600;
|
self::setLock( 3600);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 投币
|
|
||||||
|
/**
|
||||||
|
* @use 投币
|
||||||
|
* @param $aid
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private static function reward($aid): bool
|
private static function reward($aid): bool
|
||||||
{
|
{
|
||||||
$user_info = User::parseCookies();
|
$user_info = User::parseCookies();
|
||||||
@ -54,7 +63,11 @@ class MasterSite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 投币日志
|
|
||||||
|
/**
|
||||||
|
* @use 投币日志
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
protected static function coinLog(): int
|
protected static function coinLog(): int
|
||||||
{
|
{
|
||||||
$url = "https://api.bilibili.com/x/member/web/coin/log";
|
$url = "https://api.bilibili.com/x/member/web/coin/log";
|
||||||
@ -87,7 +100,12 @@ class MasterSite
|
|||||||
return $coins;
|
return $coins;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 投币操作
|
|
||||||
|
/**
|
||||||
|
* @use 投币视频
|
||||||
|
* @return bool
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
protected static function coinAdd(): bool
|
protected static function coinAdd(): bool
|
||||||
{
|
{
|
||||||
switch (getenv('USE_ADD_COIN')) {
|
switch (getenv('USE_ADD_COIN')) {
|
||||||
@ -123,7 +141,11 @@ class MasterSite
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取随机AID
|
|
||||||
|
/**
|
||||||
|
* @use 获取随机AID
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
private static function getRandomAid(): string
|
private static function getRandomAid(): string
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
@ -139,7 +161,13 @@ class MasterSite
|
|||||||
return (string)$aid;
|
return (string)$aid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 日榜AID
|
|
||||||
|
/**
|
||||||
|
* @use 获取日榜AID
|
||||||
|
* @param $num
|
||||||
|
* @return array
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
private static function getDayRankingAids($num): array
|
private static function getDayRankingAids($num): array
|
||||||
{
|
{
|
||||||
// day: 日榜1 三榜3 周榜7 月榜30
|
// day: 日榜1 三榜3 周榜7 月榜30
|
||||||
@ -166,7 +194,11 @@ class MasterSite
|
|||||||
return $aids;
|
return $aids;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分享视频
|
|
||||||
|
/**
|
||||||
|
* @use 分享视频
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private static function shareAid(): bool
|
private static function shareAid(): bool
|
||||||
{
|
{
|
||||||
# aid = 稿件av号
|
# aid = 稿件av号
|
||||||
@ -195,7 +227,11 @@ class MasterSite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 观看视频
|
|
||||||
|
/**
|
||||||
|
* @use 观看视频
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private static function watchAid(): bool
|
private static function watchAid(): bool
|
||||||
{
|
{
|
||||||
$url = "https://api.bilibili.com/x/report/click/h5";
|
$url = "https://api.bilibili.com/x/report/click/h5";
|
||||||
@ -259,7 +295,11 @@ class MasterSite
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析AID到CID
|
|
||||||
|
/**
|
||||||
|
* @use 解析AID到CID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
private static function parseAid(): array
|
private static function parseAid(): array
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -8,32 +8,33 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class MaterialObject
|
class MaterialObject
|
||||||
{
|
{
|
||||||
// 时间锁
|
use TimeLock;
|
||||||
public static $lock = 0;
|
|
||||||
// 丢弃列表
|
|
||||||
private static $discard_aid_list = [];
|
private static $discard_aid_list = [];
|
||||||
// 起始 和 结束
|
|
||||||
private static $start_aid = 0;
|
private static $start_aid = 0;
|
||||||
private static $end_aid = 0;
|
private static $end_aid = 0;
|
||||||
|
|
||||||
// RUN
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (getenv('USE_MO') == 'false') {
|
if (getenv('USE_MO') == 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 计算AID TODO 待优化
|
// 计算AID TODO 待优化
|
||||||
self::calculateAid(150, 550);
|
self::calculateAid(150, 550);
|
||||||
self::drawLottery();
|
self::drawLottery();
|
||||||
|
|
||||||
self::$lock = time() + random_int(5, 10) * 60;
|
self::setLock(random_int(5, 10) * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,11 +126,13 @@ class MaterialObject
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @use 计算 开始结束的AID
|
* @use 计算开始结束的AID
|
||||||
* @param $min
|
* @param $min
|
||||||
* @param $max
|
* @param $max
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private static function calculateAid($min, $max): bool
|
private static function calculateAid($min, $max): bool
|
||||||
{
|
{
|
||||||
120
src/plugin/Notice.php
Normal file
120
src/plugin/Notice.php
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class Notice
|
||||||
|
{
|
||||||
|
protected static $type = '';
|
||||||
|
protected static $result = '';
|
||||||
|
protected static $uname = '';
|
||||||
|
protected static $sckey = '';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 推送消息
|
||||||
|
* @param string $type
|
||||||
|
* @param string $result
|
||||||
|
*/
|
||||||
|
public static function push(string $type, string $result = '')
|
||||||
|
{
|
||||||
|
if (getenv('USE_SCKEY') == "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$type = $type;
|
||||||
|
self::$result = $result;
|
||||||
|
self::$sckey = getenv('USE_SCKEY');
|
||||||
|
self::$uname = User::userInfo() ? getenv('APP_UNAME') : getenv('APP_USER');
|
||||||
|
|
||||||
|
self::sendInfoHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 处理信息
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function sendInfoHandle(): bool
|
||||||
|
{
|
||||||
|
$now_time = date('Y-m-d H:i:s');
|
||||||
|
switch (self::$type) {
|
||||||
|
case 'anchor':
|
||||||
|
$info = [
|
||||||
|
'title' => '天选时刻获奖记录',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 在天选时刻中获得: ' . self::$result,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'raffle':
|
||||||
|
$info = [
|
||||||
|
'title' => '实物奖励获奖纪录',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 在实物奖励中获得: ' . self::$result,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'gift':
|
||||||
|
$info = [
|
||||||
|
'title' => '活动礼物获奖纪录',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 在活动礼物中获得: ' . self::$result,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'storm':
|
||||||
|
$info = [
|
||||||
|
'title' => '节奏风暴获奖纪录',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 在节奏风暴中获得: ' . self::$result,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'cookieRefresh':
|
||||||
|
$info = [
|
||||||
|
'title' => 'Cookie刷新',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 刷新Cookie: ' . self::$result,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'todaySign':
|
||||||
|
$info = [
|
||||||
|
'title' => '每日签到',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 签到: ' . self::$result,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'banned':
|
||||||
|
$info = [
|
||||||
|
'title' => '账号封禁',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 账号被封禁: 程序开始睡眠,凌晨自动唤醒,距离唤醒还有' . self::$result . '小时',
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$info = [
|
||||||
|
'title' => '推送消息异常记录',
|
||||||
|
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 推送消息key错误' . self::$type . self::$result,
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self::scSend($info);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use ServerChan发送信息
|
||||||
|
* @param array $info
|
||||||
|
*/
|
||||||
|
private static function scSend(array $info)
|
||||||
|
{
|
||||||
|
$url = "https://sc.ftqq.com/" . self::$sckey . ".send?text=" . urlencode($info['title']) . "&desp=" . urlencode($info['content']);
|
||||||
|
$data = Curl::singleRequest('get', $url);
|
||||||
|
if (is_null($data)) {
|
||||||
|
Log::warning('Server酱推送信息失败,请检查!');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,52 +8,60 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
|
||||||
class PkRaffle extends BaseRaffle
|
class PkRaffle extends BaseRaffle
|
||||||
{
|
{
|
||||||
const ACTIVE_TITLE = '大乱斗';
|
const ACTIVE_TITLE = '大乱斗';
|
||||||
const ACTIVE_SWITCH = 'USE_PK';
|
const ACTIVE_SWITCH = 'USE_PK';
|
||||||
|
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
public static $rw_lock = 0;
|
|
||||||
|
|
||||||
protected static $wait_list = [];
|
protected static $wait_list = [];
|
||||||
protected static $finish_list = [];
|
protected static $finish_list = [];
|
||||||
protected static $all_list = [];
|
protected static $all_list = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查抽奖列表
|
* @use 解析数据
|
||||||
* @param $rid
|
* @param int $room_id
|
||||||
|
* @param array $data
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected static function check($rid): bool
|
protected static function parse(int $room_id, array $data): bool
|
||||||
{
|
{
|
||||||
$payload = [
|
// 防止异常
|
||||||
'roomid' => $rid
|
if (!array_key_exists('pk', $data['data'])) {
|
||||||
];
|
return false;
|
||||||
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v1/pk/check';
|
}
|
||||||
$raw = Curl::get($url, Sign::api($payload));
|
$de_raw = $data['data']['pk'];
|
||||||
$de_raw = json_decode($raw, true);
|
if (empty($de_raw)) {
|
||||||
|
|
||||||
// 计数 && 跳出
|
|
||||||
$total = count($de_raw['data']);
|
|
||||||
if (!$total) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($i = 0; $i < $total; $i++) {
|
foreach ($de_raw as $pk) {
|
||||||
$data = [
|
// 无效抽奖
|
||||||
'raffle_id' => $de_raw['data'][$i]['pk_id'],
|
if ($pk['status'] != 1) {
|
||||||
'title' => $de_raw['data'][$i]['title'],
|
|
||||||
'room_id' => $de_raw['data'][$i]['room_id'],
|
|
||||||
'wait' => strtotime(date("Y-m-d H:i:s"))
|
|
||||||
];
|
|
||||||
if (static::toRepeatLid($data['raffle_id'])) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Statistics::addPushList(static::ACTIVE_TITLE);
|
// 去重
|
||||||
array_push(static::$wait_list, $data);
|
if (self::toRepeatLid($pk['id'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 推入列表
|
||||||
|
$data = [
|
||||||
|
'room_id' => $room_id,
|
||||||
|
'raffle_id' => $pk['id'],
|
||||||
|
'raffle_name' => '大乱斗',
|
||||||
|
'wait' => time()
|
||||||
|
];
|
||||||
|
Statistics::addPushList(self::ACTIVE_TITLE);
|
||||||
|
array_push(self::$wait_list, $data);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -83,10 +91,10 @@ class PkRaffle extends BaseRaffle
|
|||||||
* {"code":-403,"data":null,"message":"访问被拒绝","msg":"访问被拒绝"}
|
* {"code":-403,"data":null,"message":"访问被拒绝","msg":"访问被拒绝"}
|
||||||
*/
|
*/
|
||||||
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
|
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
|
||||||
Statistics::addSuccessList(static::ACTIVE_TITLE);
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['data']['award_text']}");
|
||||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$de_raw['data']['award_text']}");
|
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
||||||
} else {
|
} else {
|
||||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$de_raw['message']}");
|
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['message']}");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -8,10 +8,19 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class Sign
|
class Sign
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @use 计算sign
|
||||||
|
* @param $payload
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function api($payload)
|
public static function api($payload)
|
||||||
{
|
{
|
||||||
# iOS 6680
|
# iOS 6680
|
||||||
@ -8,61 +8,34 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class Silver
|
class Silver
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
protected static $task = [];
|
protected static $task = [];
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty(self::$task)) {
|
if (empty(self::$task)) {
|
||||||
self::pushTask();
|
self::getSilverBox();
|
||||||
} else {
|
} else {
|
||||||
self::pullTask();
|
self::openSilverBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function pushTask()
|
/**
|
||||||
{
|
* @use 获取宝箱
|
||||||
$payload = [
|
*/
|
||||||
'time_end' => self::$task['time_end'],
|
private static function getSilverBox()
|
||||||
'time_start' => self::$task['time_start']
|
|
||||||
];
|
|
||||||
$data = Curl::get('https://api.live.bilibili.com/mobile/freeSilverAward', Sign::api($payload));
|
|
||||||
$data = json_decode($data, true);
|
|
||||||
|
|
||||||
if ($data['code'] == -800) {
|
|
||||||
self::$lock = time() + 12 * 60 * 60;
|
|
||||||
Log::warning("领取宝箱失败,{$data['message']}!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($data['code'] == -903) {
|
|
||||||
Log::warning("领取宝箱失败,{$data['message']}!");
|
|
||||||
self::$task = [];
|
|
||||||
self::$lock = time() + 60;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($data['code']) && $data['code']) {
|
|
||||||
Log::warning("领取宝箱失败,{$data['message']}!");
|
|
||||||
self::$lock = time() + 60;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::notice("领取宝箱成功,Silver: {$data['data']['silver']}(+{$data['data']['awardSilver']})");
|
|
||||||
|
|
||||||
self::$task = [];
|
|
||||||
self::$lock = time() + 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function pullTask()
|
|
||||||
{
|
{
|
||||||
$payload = [];
|
$payload = [];
|
||||||
$data = Curl::get('https://api.live.bilibili.com/lottery/v1/SilverBox/getCurrentTask', Sign::api($payload));
|
$data = Curl::get('https://api.live.bilibili.com/lottery/v1/SilverBox/getCurrentTask', Sign::api($payload));
|
||||||
@ -70,7 +43,7 @@ class Silver
|
|||||||
|
|
||||||
if (isset($data['code']) && $data['code'] == -10017) {
|
if (isset($data['code']) && $data['code'] == -10017) {
|
||||||
Log::notice($data['message']);
|
Log::notice($data['message']);
|
||||||
self::$lock = time() + 24 * 60 * 60;
|
self::setLock( 24 * 60 * 60);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +59,44 @@ class Silver
|
|||||||
'time_start' => $data['data']['time_start'],
|
'time_start' => $data['data']['time_start'],
|
||||||
'time_end' => $data['data']['time_end'],
|
'time_end' => $data['data']['time_end'],
|
||||||
];
|
];
|
||||||
|
self::setLock( $data['data']['minute'] * 60 + 5);
|
||||||
|
}
|
||||||
|
|
||||||
self::$lock = time() + $data['data']['minute'] * 60 + 5;
|
|
||||||
|
/**
|
||||||
|
* @use 开启宝箱
|
||||||
|
*/
|
||||||
|
private static function openSilverBox()
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'time_end' => self::$task['time_end'],
|
||||||
|
'time_start' => self::$task['time_start']
|
||||||
|
];
|
||||||
|
$data = Curl::get('https://api.live.bilibili.com/mobile/freeSilverAward', Sign::api($payload));
|
||||||
|
$data = json_decode($data, true);
|
||||||
|
|
||||||
|
if ($data['code'] == -800) {
|
||||||
|
self::setLock( 12 * 60 * 60);
|
||||||
|
Log::warning("领取宝箱失败,{$data['message']}!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data['code'] == -903) {
|
||||||
|
Log::warning("领取宝箱失败,{$data['message']}!");
|
||||||
|
self::$task = [];
|
||||||
|
self::setLock( 60);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['code']) && $data['code']) {
|
||||||
|
Log::warning("领取宝箱失败,{$data['message']}!");
|
||||||
|
self::setLock( 60);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::notice("领取宝箱成功,Silver: {$data['data']['silver']}(+{$data['data']['awardSilver']})");
|
||||||
|
|
||||||
|
self::$task = [];
|
||||||
|
self::setLock( 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,26 +8,33 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class Silver2Coin
|
class Silver2Coin
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time() || getenv('USE_SILVER2COIN') == 'false') {
|
if (self::getLock() > time() || getenv('USE_SILVER2COIN') == 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (self::appSilver2coin() && self::pcSilver2coin()) {
|
if (self::appSilver2coin() && self::pcSilver2coin()) {
|
||||||
self::$lock = time() + 24 * 60 * 60;
|
self::setLock(24 * 60 * 60);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self::$lock = time() + 3600;
|
self::setLock(3600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// APP API
|
/**
|
||||||
|
* @use app兑换
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected static function appSilver2coin(): bool
|
protected static function appSilver2coin(): bool
|
||||||
{
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
@ -46,13 +53,17 @@ class Silver2Coin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PC API
|
|
||||||
|
/**
|
||||||
|
* @use pc兑换
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected static function pcSilver2coin(): bool
|
protected static function pcSilver2coin(): bool
|
||||||
{
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
$payload = [];
|
$payload = [];
|
||||||
|
$url = "https://api.live.bilibili.com/exchange/silver2coin";
|
||||||
$url = "https://api.live.bilibili.com/pay/v1/Exchange/silver2coin";
|
$url = "https://api.live.bilibili.com/pay/v1/Exchange/silver2coin";
|
||||||
$url1 = "https://api.live.bilibili.com/exchange/silver2coin";
|
|
||||||
|
|
||||||
$raw = Curl::get($url, Sign::api($payload));
|
$raw = Curl::get($url, Sign::api($payload));
|
||||||
$de_raw = json_decode($raw, true);
|
$de_raw = json_decode($raw, true);
|
||||||
80
src/plugin/Sleep.php
Normal file
80
src/plugin/Sleep.php
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
|
||||||
|
class Sleep
|
||||||
|
{
|
||||||
|
use TimeLock;
|
||||||
|
// TODO 黑白名单 考虑添加到每个插件内部自动添加
|
||||||
|
private static $fillable = ['Login', 'Sleep', 'Daily', 'MasterSite', 'GiftSend', 'Task', 'Silver2Coin', 'GroupSignIn', 'GiftHeart', 'AwardRecord', 'Statistics'];
|
||||||
|
private static $guarded = ['Barrage', 'Heart', 'Silver', 'MaterialObject', 'AloneTcpClient', 'ZoneTcpClient', 'StormRaffle', 'GuardRaffle', 'PkRaffle', 'GiftRaffle', 'AnchorRaffle'];
|
||||||
|
private static $sleep_section = [];
|
||||||
|
|
||||||
|
|
||||||
|
public static function run()
|
||||||
|
{
|
||||||
|
if (getenv('USE_SLEEP') == 'false' || self::getLock() > time()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self::isPause();
|
||||||
|
self::isRefuse();
|
||||||
|
self::setLock(5 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function isPause()
|
||||||
|
{
|
||||||
|
self::$sleep_section = empty(self::$filter_type) ? explode(',', getenv('SLEEP_SECTION')) : self::$sleep_section;
|
||||||
|
if (in_array(date('H'), self::$sleep_section)) {
|
||||||
|
$unlock_time = 60 * 60;
|
||||||
|
self::stopProc($unlock_time);
|
||||||
|
Log::warning('进入自定义休眠时间范围,暂停非必要任务,自动开启!');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function isRefuse()
|
||||||
|
{
|
||||||
|
$payload = [];
|
||||||
|
$raw = Curl::get('https://api.live.bilibili.com/mobile/freeSilverAward', Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
if ($de_raw['msg'] == '访问被拒绝') {
|
||||||
|
$unlock_time = strtotime(date("Y-m-d", strtotime("+1 day", time()))) - time();
|
||||||
|
self::stopProc($unlock_time);
|
||||||
|
Log::warning('账号拒绝访问,暂停非必要任务,自动开启!');
|
||||||
|
// 推送被ban信息
|
||||||
|
Notice::push('banned', floor($unlock_time / 60 / 60));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 停止运行
|
||||||
|
* @param int $unlock_time
|
||||||
|
*/
|
||||||
|
private static function stopProc(int $unlock_time)
|
||||||
|
{
|
||||||
|
$unlock_time = $unlock_time + 1 * 60;
|
||||||
|
// 检测时间提前5分钟
|
||||||
|
self::setLock($unlock_time - 5 * 60);
|
||||||
|
foreach (self::$fillable as $classname) {
|
||||||
|
Log::info("插件 {$classname} 白名单,保持当前状态继续");
|
||||||
|
}
|
||||||
|
foreach (self::$guarded as $classname) {
|
||||||
|
Log::info("插件 {$classname} 黑名单,锁定状态将于" . date("Y-m-d H:i", time() + $unlock_time) . "解除");
|
||||||
|
call_user_func(array(__NAMESPACE__ . '\\' . $classname, 'setLock'), $unlock_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,32 +8,37 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
|
||||||
class Statistics
|
class Statistics
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
// 推送 参加 成功
|
|
||||||
private static $push_list = [];
|
private static $push_list = [];
|
||||||
private static $join_list = [];
|
private static $join_list = [];
|
||||||
private static $success_list = [];
|
private static $success_list = [];
|
||||||
|
|
||||||
|
|
||||||
// 日志
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self::getStormResult();
|
self::outputResult();
|
||||||
|
|
||||||
self::$lock = time() + 5 * 60;
|
self::setLock(5 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 添加推送
|
/**
|
||||||
|
* @use 添加推送
|
||||||
|
* @param string $key
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function addPushList(string $key): bool
|
public static function addPushList(string $key): bool
|
||||||
{
|
{
|
||||||
// 初始化三个必要值
|
// 初始化三个必要值
|
||||||
@ -47,22 +52,36 @@ class Statistics
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加参与
|
|
||||||
|
/**
|
||||||
|
* @use 添加参与
|
||||||
|
* @param string $key
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function addJoinList(string $key): bool
|
public static function addJoinList(string $key): bool
|
||||||
{
|
{
|
||||||
array_push(self::$join_list[$key], 1);
|
array_push(self::$join_list[$key], 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加成功
|
|
||||||
|
/**
|
||||||
|
* @use 添加成功
|
||||||
|
* @param string $key
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function addSuccessList(string $key): bool
|
public static function addSuccessList(string $key): bool
|
||||||
{
|
{
|
||||||
array_push(self::$success_list[$key], 1);
|
array_push(self::$success_list[$key], 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取结果
|
|
||||||
private static function getStormResult(): bool
|
/**
|
||||||
|
* @use 输出结果
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function outputResult(): bool
|
||||||
{
|
{
|
||||||
if (empty(self::$push_list)) {
|
if (empty(self::$push_list)) {
|
||||||
return false;
|
return false;
|
||||||
141
src/plugin/StormRaffle.php
Normal file
141
src/plugin/StormRaffle.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
class StormRaffle extends BaseRaffle
|
||||||
|
{
|
||||||
|
const ACTIVE_TITLE = '节奏风暴';
|
||||||
|
const ACTIVE_SWITCH = 'USE_STORM';
|
||||||
|
|
||||||
|
use TimeLock;
|
||||||
|
|
||||||
|
protected static $wait_list = [];
|
||||||
|
protected static $finish_list = [];
|
||||||
|
protected static $all_list = [];
|
||||||
|
|
||||||
|
private static $drop_rate = null;
|
||||||
|
private static $attempt = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 解析数据
|
||||||
|
* @param int $room_id
|
||||||
|
* @param array $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function parse(int $room_id, array $data): bool
|
||||||
|
{
|
||||||
|
// 防止异常
|
||||||
|
if (!array_key_exists('storm', $data['data'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$de_raw = $data['data']['storm'];
|
||||||
|
if (empty($de_raw)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 无效抽奖
|
||||||
|
if ($de_raw['hadJoin'] != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 过滤抽奖范围
|
||||||
|
self::$drop_rate = getenv('STORM_DROPRATE') !== "" ? (int)getenv('STORM_DROPRATE') : 0;
|
||||||
|
if (mt_rand(1, 100) <= (int)self::$drop_rate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 去重
|
||||||
|
if (self::toRepeatLid($de_raw['id'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 推入列表
|
||||||
|
$data = [
|
||||||
|
'room_id' => $room_id,
|
||||||
|
'raffle_id' => $de_raw['id'],
|
||||||
|
'raffle_name' => '节奏风暴',
|
||||||
|
'wait' => time()
|
||||||
|
];
|
||||||
|
Statistics::addPushList(self::ACTIVE_TITLE);
|
||||||
|
array_push(self::$wait_list, $data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化日志输出
|
||||||
|
* @param $id
|
||||||
|
* @param $num
|
||||||
|
* @param $info
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function formatInfo($id, $num, $info): string
|
||||||
|
{
|
||||||
|
return "风暴 {$id} 请求 {$num} 状态 {$info}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 请求抽奖
|
||||||
|
* @param array $data
|
||||||
|
* @return bool
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected static function lottery(array $data): bool
|
||||||
|
{
|
||||||
|
self::$attempt = getenv('STORM_ATTEMPT') !== "" ? explode(',', getenv('STORM_ATTEMPT')) : [30, 50];
|
||||||
|
$num = random_int((int)self::$attempt[0], (int)self::$attempt[1]);
|
||||||
|
$user_info = User::parseCookies();
|
||||||
|
$payload = [
|
||||||
|
'id' => $data['raffle_id'],
|
||||||
|
'roomid' => $data['room_id'],
|
||||||
|
"color" => "16772431",
|
||||||
|
"captcha_token" => "",
|
||||||
|
"captcha_phrase" => "",
|
||||||
|
"token" => $user_info['token'],
|
||||||
|
"csrf_token" => $user_info['token'],
|
||||||
|
"visit_id" => "",
|
||||||
|
];
|
||||||
|
$url = 'https://api.live.bilibili.com/lottery/v1/Storm/join';
|
||||||
|
for ($i = 1; $i < $num; $i++) {
|
||||||
|
$raw = Curl::post($url, Sign::api($payload));
|
||||||
|
$de_raw = json_decode($raw, true);
|
||||||
|
if ($de_raw['code'] == 429 || $de_raw['code'] == -429) {
|
||||||
|
Log::notice(self::formatInfo($data['raffle_id'], $num, '节奏风暴未实名或异常验证码'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isset($de_raw['data']) && empty($de_raw['data'])) {
|
||||||
|
Log::notice(self::formatInfo($data['raffle_id'], $num, '节奏风暴在小黑屋'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($de_raw['code'] == 0) {
|
||||||
|
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
||||||
|
Log::notice(self::formatInfo($data['raffle_id'], $num, $de_raw['data']['mobile_content']));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($de_raw['msg'] == '节奏风暴不存在') {
|
||||||
|
Log::notice(self::formatInfo($data['raffle_id'], $num, '节奏风暴已结束'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($de_raw['msg'] == '已经领取奖励') {
|
||||||
|
Log::notice(self::formatInfo($data['raffle_id'], $num, '节奏风暴已经领取'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($de_raw['msg'] == '你错过了奖励,下次要更快一点哦~') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log::notice(self::formatInfo($data['raffle_id'], $num, $de_raw['msg']));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,22 +8,23 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
class Task
|
class Task
|
||||||
{
|
{
|
||||||
public static $lock = 0;
|
use TimeLock;
|
||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if (self::$lock > time()) {
|
if (self::getLock() > time()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info('正在检查每日任务...');
|
|
||||||
|
|
||||||
$data = self::check();
|
$data = self::check();
|
||||||
|
|
||||||
if (isset($data['data']['double_watch_info'])) {
|
if (isset($data['data']['double_watch_info'])) {
|
||||||
self::double_watch_info($data['data']['double_watch_info']);
|
self::double_watch_info($data['data']['double_watch_info']);
|
||||||
}
|
}
|
||||||
@ -31,15 +32,19 @@ class Task
|
|||||||
self::sign_info($data['data']['sign_info']);
|
self::sign_info($data['data']['sign_info']);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$lock = time() + 3600;
|
self::setLock(8 * 60 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function check()
|
/**
|
||||||
|
* @use 检查每日任务
|
||||||
|
* @return bool|mixed|string
|
||||||
|
*/
|
||||||
|
private static function check()
|
||||||
{
|
{
|
||||||
$payload = [];
|
$payload = [];
|
||||||
$data = Curl::get('https://api.live.bilibili.com/i/api/taskInfo', Sign::api($payload));
|
$data = Curl::get('https://api.live.bilibili.com/i/api/taskInfo', Sign::api($payload));
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
|
Log::info('正在检查每日任务...');
|
||||||
if (isset($data['code']) && $data['code']) {
|
if (isset($data['code']) && $data['code']) {
|
||||||
Log::warning('每日任务检查失败!', ['msg' => $data['message']]);
|
Log::warning('每日任务检查失败!', ['msg' => $data['message']]);
|
||||||
}
|
}
|
||||||
@ -47,7 +52,11 @@ class Task
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function sign_info($info)
|
/**
|
||||||
|
* @use 每日签到
|
||||||
|
* @param $info
|
||||||
|
*/
|
||||||
|
private static function sign_info($info)
|
||||||
{
|
{
|
||||||
Log::info('检查任务「每日签到」...');
|
Log::info('检查任务「每日签到」...');
|
||||||
|
|
||||||
@ -65,11 +74,15 @@ class Task
|
|||||||
} else {
|
} else {
|
||||||
Log::info('签到成功');
|
Log::info('签到成功');
|
||||||
// 推送签到信息
|
// 推送签到信息
|
||||||
Notice::run('todaySign', $data['message']);
|
Notice::push('todaySign', $data['message']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function double_watch_info($info)
|
/**
|
||||||
|
* @use 双端任务
|
||||||
|
* @param $info
|
||||||
|
*/
|
||||||
|
private static function double_watch_info($info)
|
||||||
{
|
{
|
||||||
Log::info('检查任务「双端观看直播」...');
|
Log::info('检查任务「双端观看直播」...');
|
||||||
|
|
||||||
@ -77,12 +90,10 @@ class Task
|
|||||||
Log::notice('已经领取奖励');
|
Log::notice('已经领取奖励');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($info['mobile_watch'] != 1 || $info['web_watch'] != 1) {
|
if ($info['mobile_watch'] != 1 || $info['web_watch'] != 1) {
|
||||||
Log::notice('任务未完成,请等待');
|
Log::notice('任务未完成,请等待');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload = [
|
$payload = [
|
||||||
'task_id' => 'double_watch_task',
|
'task_id' => 'double_watch_task',
|
||||||
];
|
];
|
||||||
@ -8,16 +8,22 @@
|
|||||||
* Updated: 2019 ~ 2020
|
* Updated: 2019 ~ 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace lkeme\BiliHelper;
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Core\Curl;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
use BiliHelper\Core\Config;
|
||||||
|
|
||||||
|
|
||||||
class User
|
class User
|
||||||
{
|
{
|
||||||
// RUN
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// 实名检测
|
|
||||||
|
/**
|
||||||
|
* @use 实名检测
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function realNameCheck(): bool
|
public static function realNameCheck(): bool
|
||||||
{
|
{
|
||||||
$payload = [];
|
$payload = [];
|
||||||
@ -30,7 +36,11 @@ class User
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 老爷检测
|
|
||||||
|
/**
|
||||||
|
* @use 是否是老爷
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function isMaster(): bool
|
public static function isMaster(): bool
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
@ -46,7 +56,11 @@ class User
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户名写入
|
|
||||||
|
/**
|
||||||
|
* @use 用户名写入
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function userInfo(): bool
|
public static function userInfo(): bool
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
@ -59,13 +73,17 @@ class User
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ($de_raw['msg'] == 'ok') {
|
if ($de_raw['msg'] == 'ok') {
|
||||||
File::writeNewEnvironmentFileWith('APP_UNAME', $de_raw['data']['uname']);
|
Config::put('APP_UNAME', $de_raw['data']['uname']);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//转换信息
|
|
||||||
|
/**
|
||||||
|
* @use 转换信息
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function parseCookies(): array
|
public static function parseCookies(): array
|
||||||
{
|
{
|
||||||
$cookies = getenv('COOKIE');
|
$cookies = getenv('COOKIE');
|
||||||
427
src/plugin/ZoneTcpClient.php
Normal file
427
src/plugin/ZoneTcpClient.php
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Plugin;
|
||||||
|
|
||||||
|
use BiliHelper\Core\Log;
|
||||||
|
use BiliHelper\Util\TimeLock;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Socket\Raw\Factory;
|
||||||
|
|
||||||
|
class ZoneTcpClient
|
||||||
|
{
|
||||||
|
use TimeLock;
|
||||||
|
private static $raffle_id = 0;
|
||||||
|
private static $raffle_list = [];
|
||||||
|
private static $server_addr = null;
|
||||||
|
private static $server_key = null;
|
||||||
|
|
||||||
|
private static $area_id;
|
||||||
|
private static $room_id;
|
||||||
|
private static $client;
|
||||||
|
private static $client_maps = [];
|
||||||
|
private static $trigger_restart = [];
|
||||||
|
private static $socket_timeout = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 入口
|
||||||
|
*/
|
||||||
|
public static function run()
|
||||||
|
{
|
||||||
|
if (self::getLock() > time() || getenv('USE_ZONE_SERVER') == 'false') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self::init();
|
||||||
|
self::updateConnection();
|
||||||
|
self::heartBeat();
|
||||||
|
self::receive();
|
||||||
|
self::pushHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 初始化
|
||||||
|
*/
|
||||||
|
private static function init()
|
||||||
|
{
|
||||||
|
if (empty(getenv('ZONE_SERVER_ADDR'))) {
|
||||||
|
exit('推送服务器信息不完整, 请检查配置文件!');
|
||||||
|
}
|
||||||
|
if (!self::$server_addr) {
|
||||||
|
self::$server_addr = getenv('ZONE_SERVER_ADDR');
|
||||||
|
}
|
||||||
|
if (!self::$client) {
|
||||||
|
self::initConnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 初始化连接
|
||||||
|
*/
|
||||||
|
private static function initConnect()
|
||||||
|
{
|
||||||
|
$areas = Live::fetchLiveAreas();
|
||||||
|
foreach ($areas as $area_id) {
|
||||||
|
self::$client_maps["server{$area_id}"] = ["area_id" => null, "room_id" => null, "client" => null, "heart_beat" => 0];
|
||||||
|
self::triggerReConnect([
|
||||||
|
'area_id' => $area_id,
|
||||||
|
'wait_time' => time()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 触发重连
|
||||||
|
* @param array $area_data
|
||||||
|
*/
|
||||||
|
private static function triggerReConnect(array $area_data)
|
||||||
|
{
|
||||||
|
array_push(self::$trigger_restart, $area_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 更新连接
|
||||||
|
*/
|
||||||
|
private static function updateConnection()
|
||||||
|
{
|
||||||
|
$num = count(self::$trigger_restart);
|
||||||
|
for ($i = 0; $i < $num; $i++) {
|
||||||
|
$area_data = array_shift(self::$trigger_restart);
|
||||||
|
if (is_null($area_data)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (time() < $area_data['wait_time']) {
|
||||||
|
array_push(self::$trigger_restart, $area_data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log::notice("update_connections triggered, info: {$area_data['area_id']}");
|
||||||
|
$area_info = Live::areaToRid($area_data['area_id']);
|
||||||
|
// $area_info = [
|
||||||
|
// 'area_id' => $area_id,
|
||||||
|
// 'room_id' => 23058
|
||||||
|
// ];
|
||||||
|
self::update($area_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 更新操作
|
||||||
|
* @param array $area_info
|
||||||
|
*/
|
||||||
|
private static function update(array $area_info)
|
||||||
|
{
|
||||||
|
self::$area_id = $area_info['area_id'];
|
||||||
|
self::$room_id = $area_info['room_id'];
|
||||||
|
try {
|
||||||
|
self::$client = (new Factory())->createClient(self::$server_addr, 40);
|
||||||
|
self::$client->setBlocking(false);
|
||||||
|
self::sendHandShake();
|
||||||
|
self::$client_maps["server" . self::$area_id]['client'] = self::$client;
|
||||||
|
self::$client_maps["server" . self::$area_id]['area_id'] = self::$area_id;
|
||||||
|
self::$client_maps["server" . self::$area_id]['room_id'] = self::$room_id;
|
||||||
|
self::$client_maps["server" . self::$area_id]['heart_beat'] = time() + 20;
|
||||||
|
Log::info("连接到 " . self::$client->getPeerName() . "#" . self::$area_id . " 推送服务器");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error("连接到 #" . self::$area_id . " 推送服务器失败, {$e->getMessage()}");
|
||||||
|
self::triggerReConnect([
|
||||||
|
'area_id' => self::$area_id,
|
||||||
|
'wait_time' => time() + 60
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断字符串是否为 Json 格式
|
||||||
|
* @param string $data Json 字符串
|
||||||
|
* @param bool $assoc 是否返回对象or关联数组,默认返回关联数组
|
||||||
|
* @return array|bool|object 成功返回转换后的对象或数组,失败返回 false
|
||||||
|
*/
|
||||||
|
private static function analyJson($data = '', $assoc = true)
|
||||||
|
{
|
||||||
|
$data = json_decode($data, $assoc);
|
||||||
|
if (($data && is_object($data)) || (is_array($data) && !empty($data))) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 响应数据
|
||||||
|
* @param $msg
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function onMessage($msg)
|
||||||
|
{
|
||||||
|
// 心跳后回复人气
|
||||||
|
if (strlen($msg) == 4) {
|
||||||
|
// $num = unpack('N', $msg)[1];
|
||||||
|
// Log::info("当前直播间现有 {$num} 人聚众搞基!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$de_raw = self::analyJson($msg, true);
|
||||||
|
// 进入房间返回
|
||||||
|
if (isset($de_raw['code']) && !$de_raw['code']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 部分cmd抽风
|
||||||
|
if (!$de_raw || !isset($de_raw['cmd'])) {
|
||||||
|
Log::warning("解析错误: {$msg}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$data = [];
|
||||||
|
switch ($de_raw['cmd']) {
|
||||||
|
case 'NOTICE_MSG':
|
||||||
|
$msg_type = $de_raw['msg_type'];
|
||||||
|
$msg_self = $de_raw['msg_self'];
|
||||||
|
$msg_common = str_replace(' ', '', $de_raw['msg_common']);
|
||||||
|
$real_room_id = $de_raw['real_roomid'];
|
||||||
|
if (in_array($msg_type, [2, 8])) {
|
||||||
|
$data = [
|
||||||
|
'room_id' => $real_room_id,
|
||||||
|
'raffle_id' => self::$raffle_id++,
|
||||||
|
'raffle_title' => $msg_self,
|
||||||
|
'raffle_type' => 'raffle',
|
||||||
|
'source' => $msg
|
||||||
|
];
|
||||||
|
// echo self::$room_id . '--' . $real_room_id . PHP_EOL;
|
||||||
|
}
|
||||||
|
if ($msg_type == 6 && strpos($msg_common, '节奏风暴') !== false) {
|
||||||
|
$data = [
|
||||||
|
'room_id' => $real_room_id,
|
||||||
|
'raffle_id' => self::$raffle_id++,
|
||||||
|
'raffle_title' => '节奏风暴',
|
||||||
|
'raffle_type' => 'raffle',
|
||||||
|
'source' => $msg
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'GUARD_MSG':
|
||||||
|
$data = [
|
||||||
|
'room_id' => $de_raw['roomid'],
|
||||||
|
'raffle_id' => self::$raffle_id++,
|
||||||
|
'raffle_title' => '总督舰长',
|
||||||
|
'raffle_type' => 'raffle',
|
||||||
|
'source' => $msg
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'SPECIAL_GIFT':
|
||||||
|
if (array_key_exists('39', $de_raw['data'])) {
|
||||||
|
if ($de_raw['data']['39']['action'] == 'start') {
|
||||||
|
$data = [
|
||||||
|
'room_id' => $de_raw['roomid'],
|
||||||
|
'raffle_id' => self::$raffle_id++,
|
||||||
|
'raffle_title' => '节奏风暴',
|
||||||
|
'raffle_type' => 'raffle',
|
||||||
|
'source' => $msg
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'SYS_GIFT':
|
||||||
|
/**
|
||||||
|
* 系统礼物消息, 广播
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case 'SYS_MSG':
|
||||||
|
/**
|
||||||
|
* 系统消息, 广播
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
// TODO 支持更多消息类型
|
||||||
|
default:
|
||||||
|
$data = [];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($data)) {
|
||||||
|
unset($data['source']);
|
||||||
|
if (!isset(self::$raffle_list[$data['raffle_type']])) {
|
||||||
|
self::$raffle_list[$data['raffle_type']] = [];
|
||||||
|
}
|
||||||
|
array_push(self::$raffle_list[$data['raffle_type']], $data);
|
||||||
|
// Log::info("获取到分区 #" . self::$area_id . "# {$data['source']}");
|
||||||
|
// print_r($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @推送到上游处理
|
||||||
|
*/
|
||||||
|
private static function pushHandle()
|
||||||
|
{
|
||||||
|
foreach (self::$raffle_list as $type => $data) {
|
||||||
|
$temp_room_id = 0;
|
||||||
|
foreach (self::$raffle_list[$type] as $raffle) {
|
||||||
|
if ($temp_room_id != $raffle['room_id']) {
|
||||||
|
DataTreating::distribute($raffle);
|
||||||
|
$temp_room_id = $raffle['room_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::$raffle_list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 响应关闭
|
||||||
|
* @param $client
|
||||||
|
*/
|
||||||
|
private static function onClosed($client)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 发送握手包
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function sendHandShake()
|
||||||
|
{
|
||||||
|
return self::writer(self::genHandshakePkg(self::$room_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 心跳包
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function genHeartBeatPkg(): string
|
||||||
|
{
|
||||||
|
return self::packMsg('', 0x0002);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 握手包
|
||||||
|
* @param $room_id
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function genHandshakePkg($room_id): string
|
||||||
|
{
|
||||||
|
return self::packMsg(json_encode([
|
||||||
|
'uid' => mt_rand(1000000, 2999999),
|
||||||
|
'roomid' => intval($room_id),
|
||||||
|
]), 0x0007);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 打包数据
|
||||||
|
* @param $value
|
||||||
|
* @param $option
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function packMsg($value, $option)
|
||||||
|
{
|
||||||
|
$head = pack('NnnNN', 0x10 + strlen($value), 0x10, 0x01, $option, 0x0001);
|
||||||
|
return $head . $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 解包数据
|
||||||
|
* @param $value
|
||||||
|
* @return int|mixed
|
||||||
|
*/
|
||||||
|
private static function unPackMsg($value)
|
||||||
|
{
|
||||||
|
$res = unpack('N', $value);
|
||||||
|
return $res[1] - 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 心跳
|
||||||
|
*/
|
||||||
|
private static function heartBeat()
|
||||||
|
{
|
||||||
|
foreach (self::$client_maps as $key => $client_info) {
|
||||||
|
if ($client_info['heart_beat'] > time()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self::$client = $client_info['client'];
|
||||||
|
self::$area_id = $client_info['area_id'];
|
||||||
|
self::$room_id = $client_info['room_id'];
|
||||||
|
self::writer(self::genHeartBeatPkg());
|
||||||
|
self::$client_maps[$key]['heart_beat'] = time() + 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 读数据
|
||||||
|
* @param $length
|
||||||
|
* @return array|bool|false
|
||||||
|
*/
|
||||||
|
private static function reader($length)
|
||||||
|
{
|
||||||
|
$data = false;
|
||||||
|
try {
|
||||||
|
while (self::$client->selectRead(self::$socket_timeout)) {
|
||||||
|
$data = self::$client->read($length);
|
||||||
|
if (!$data) {
|
||||||
|
throw new Exception("Connection failure");
|
||||||
|
}
|
||||||
|
if ($length == 16) $data = self::unPackMsg($data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
self::triggerReConnect([
|
||||||
|
'area_id' => self::$area_id,
|
||||||
|
'wait_time' => time() + 60
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 写数据
|
||||||
|
* @param $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function writer($data)
|
||||||
|
{
|
||||||
|
$status = false;
|
||||||
|
try {
|
||||||
|
while (self::$client->selectWrite(self::$socket_timeout)) {
|
||||||
|
$status = self::$client->write($data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
self::triggerReConnect([
|
||||||
|
'area_id' => self::$area_id,
|
||||||
|
'wait_time' => time() + 60
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 读取数据
|
||||||
|
*/
|
||||||
|
private static function receive()
|
||||||
|
{
|
||||||
|
foreach (self::$client_maps as $client_info) {
|
||||||
|
self::$client = $client_info['client'];
|
||||||
|
self::$area_id = $client_info['area_id'];
|
||||||
|
self::$room_id = $client_info['room_id'];
|
||||||
|
$len_body = self::reader(16);
|
||||||
|
if (!$len_body) {
|
||||||
|
// 长度为0 ,空信息
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log::debug("(len=$len_body)");
|
||||||
|
$body = self::reader($len_body);
|
||||||
|
self::onMessage($body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/util/TimeLock.php
Normal file
38
src/util/TimeLock.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Website: https://mudew.com/
|
||||||
|
* Author: Lkeme
|
||||||
|
* License: The MIT License
|
||||||
|
* Email: Useri@live.cn
|
||||||
|
* Updated: 2019 ~ 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BiliHelper\Util;
|
||||||
|
|
||||||
|
|
||||||
|
trait TimeLock
|
||||||
|
{
|
||||||
|
public static $lock = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 设置时间
|
||||||
|
* @param int $lock
|
||||||
|
*/
|
||||||
|
public static function setLock(int $lock)
|
||||||
|
{
|
||||||
|
static::$lock = time() + $lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @use 获取时间
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function getLock(): int
|
||||||
|
{
|
||||||
|
return static::$lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user