mirror of
https://github.com/lkeme/BiliHelper-personal.git
synced 2025-12-19 01:20:08 +08:00
[update] Version 0.1.0
This commit is contained in:
parent
4edfb295b4
commit
44e54d38a8
70
CHANGELOG.md
70
CHANGELOG.md
@ -1,62 +1,40 @@
|
||||
# Release Notes
|
||||
# 本项目Log
|
||||
|
||||
## v0.0.1.191223 alpha (2019-12-23)
|
||||
## v0.1.0.191227 alpha (2019-12-27)
|
||||
|
||||
### Added
|
||||
- anchor(beta)
|
||||
-
|
||||
- 新增备用官方分区监控
|
||||
- 新增按勋章亲密度赠送
|
||||
- 新增天选时刻获奖推送
|
||||
-
|
||||
|
||||
### Changed
|
||||
- 优化部分架构
|
||||
- 优化独立监控
|
||||
- 优化监控逻辑
|
||||
- 优化礼物赠送
|
||||
- 优化通用抽奖
|
||||
- 优化推送逻辑
|
||||
-
|
||||
|
||||
### Fixed
|
||||
-
|
||||
- 修复部分日志显示
|
||||
- 修复数据统计异常
|
||||
- 修复瓜子宝箱异常
|
||||
- 修复Server酱异常
|
||||
- 修复天选时刻异常
|
||||
- 修复抽奖数据异常
|
||||
- 修复部分已知BUG
|
||||
- 修复获奖推送通知
|
||||
-
|
||||
|
||||
## v0.0.1.191030 alpha (2019-10-30)
|
||||
## v0.0.5.191223 alpha (2019-12-23)
|
||||
|
||||
### Added
|
||||
-
|
||||
|
||||
### 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.4.191030 alpha (2019-10-30)
|
||||
|
||||
## v0.0.3.190730 alpha (2019-07-30)
|
||||
|
||||
## v0.0.2.190723 alpha (2019-07-23)
|
||||
|
||||
## v0.0.1.190713 alpha (2019-07-13)
|
||||
|
||||
### Added
|
||||
- Initialization
|
||||
|
||||
### Changed
|
||||
- Initialization
|
||||
|
||||
### Fixed
|
||||
- Initialization
|
||||
|
||||
78
DOC.md
78
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 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">
|
||||
</p>
|
||||
|
||||
@ -17,35 +17,40 @@ B 站直播实用脚本
|
||||
|
||||
|plugin |version |description |
|
||||
|--------------------|--------------------|--------------------|
|
||||
|Daily |19.12.23 |每日背包奖励 |
|
||||
|GiftSend |19.12.23 |自动清空过期礼物 |
|
||||
|Heart |19.12.23 |双端直播间心跳 |
|
||||
|Login |19.12.23 |帐号登录组件 |
|
||||
|Silver |19.12.23 |自动领宝箱 |
|
||||
|Task |19.12.23 |每日任务 |
|
||||
|GiftHeart |19.12.23 |心跳礼物 |
|
||||
|Silver2Coin |19.12.23 |银瓜子换硬币 |
|
||||
|MaterialObject |19.12.23 |实物抽奖 |
|
||||
|GroupSignIn |19.12.23 |应援团签到 |
|
||||
|Storm |19.12.23 |节奏风暴 |
|
||||
|Notice |19.12.23 |Server酱 |
|
||||
|UnifyRaffle |19.12.23 |统一活动抽奖 |
|
||||
|MasterSite |19.12.23 |主站(观看、分享、投币)|
|
||||
|Guard |19.12.23 |舰长上船亲密度 |
|
||||
|PkRaffle |19.12.23 |大乱斗 |
|
||||
|Anchor |19.12.23 |天选时刻 |
|
||||
|Login |19.12.27 |账号登录 |
|
||||
|Sleep |19.12.27 |休眠控制 |
|
||||
|MasterSite |19.12.27 |主站助手 |
|
||||
|Daily |19.12.27 |每日礼包 |
|
||||
|Heart |19.12.27 |双端心跳 |
|
||||
|Task |19.12.27 |每日任务 |
|
||||
|Silver |19.12.27 |银瓜子宝箱 |
|
||||
|Barrage |19.12.27 |活跃弹幕 |
|
||||
|Silver2Coin |19.12.27 |银瓜子换硬币 |
|
||||
|GiftSend |19.12.27 |礼物赠送 |
|
||||
|GroupSignIn |19.12.27 |友爱社签到 |
|
||||
|GiftHeart |19.12.27 |心跳礼物 |
|
||||
|MaterialObject |19.12.27 |实物抽奖 |
|
||||
|AloneTcpClient |19.12.27 |独立监控 |
|
||||
|ZoneTcpClient |19.12.27 |分区监控 |
|
||||
|StormRaffle |19.12.27 |节奏风暴 |
|
||||
|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_zlib |
|
||||
|php_mbstring |
|
||||
|待添加 |
|
||||
|
||||
通常使用 `composer` 工具会自动检测上述依赖问题。
|
||||
|
||||
@ -79,11 +83,7 @@ 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 问题
|
||||
|
||||
`user.conf` 文件中有个 `ROOM_ID` 配置,填写此项可以清空临过期礼物给指定直播间。
|
||||
文件 `user.conf` 里
|
||||
|
||||
`ROOM_ID` 配置,填写此项可以清空临过期礼物给指定直播间。
|
||||
|
||||
`ROOM_LIST` 配置,使用长位直播间,填写此项可以清空临礼物给指定有勋章的直播间。
|
||||
|
||||
`FEED_FILL` 配置,搭配上一条使用,使用过期礼物或者倒序使用正常礼物。
|
||||
|
||||
`SOCKET_ROOM_ID` 配置,监控使用,暂时没用到。
|
||||
|
||||
通常可以在直播间页面的 url 获取到它
|
||||
```
|
||||
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 许可证
|
||||
|
||||
|
||||
@ -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-zlib": "*",
|
||||
"ext-mbstring": "*",
|
||||
"vlucas/phpdotenv": "^2.4",
|
||||
"monolog/monolog": "^1.23",
|
||||
"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",
|
||||
"authors": [
|
||||
@ -25,7 +25,9 @@
|
||||
],
|
||||
"autoload": {
|
||||
"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",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d09e06835f7ff6a06fcb74285e6617c5",
|
||||
"content-hash": "6034c5a467eb270c2c7d1ce12d7277fd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bramus/ansi-php",
|
||||
@ -245,6 +245,67 @@
|
||||
],
|
||||
"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",
|
||||
"version": "1.1.2",
|
||||
@ -364,16 +425,16 @@
|
||||
},
|
||||
{
|
||||
"name": "vlucas/phpdotenv",
|
||||
"version": "v2.6.1",
|
||||
"version": "v4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vlucas/phpdotenv.git",
|
||||
"reference": "2a7dcf7e3e02dc5e701004e51a6f304b713107d5"
|
||||
"reference": "0176075a1b7ee9cf86f70143ec79edf7072c975a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2a7dcf7e3e02dc5e701004e51a6f304b713107d5",
|
||||
"reference": "2a7dcf7e3e02dc5e701004e51a6f304b713107d5",
|
||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/0176075a1b7ee9cf86f70143ec79edf7072c975a",
|
||||
"reference": "0176075a1b7ee9cf86f70143ec79edf7072c975a",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -383,16 +444,18 @@
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9",
|
||||
"php": "^5.5.9 || ^7.0",
|
||||
"phpoption/phpoption": "^1.7.1",
|
||||
"symfony/polyfill-ctype": "^1.9"
|
||||
},
|
||||
"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",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.6-dev"
|
||||
"dev-master": "4.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -405,10 +468,15 @@
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Graham Campbell",
|
||||
"email": "graham@alt-three.com",
|
||||
"homepage": "https://gjcampbell.co.uk/"
|
||||
},
|
||||
{
|
||||
"name": "Vance Lucas",
|
||||
"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.",
|
||||
@ -417,7 +485,7 @@
|
||||
"env",
|
||||
"environment"
|
||||
],
|
||||
"time": "2019-01-29T11:11:52+00:00"
|
||||
"time": "2019-12-14T13:59:29+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
||||
@ -11,32 +11,6 @@ ACCESS_TOKEN=
|
||||
REFRESH_TOKEN=
|
||||
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=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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
|
||||
//autoload
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
set_time_limit(0);
|
||||
header("Content-Type:text/html; charset=utf-8");
|
||||
date_default_timezone_set('Asia/Shanghai');
|
||||
$filename = isset($argv[1]) ? $argv[1] : 'user.conf';
|
||||
|
||||
class Index
|
||||
{
|
||||
public static $conf_file = null;
|
||||
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);
|
||||
$app = new BiliHelper\Core\App();
|
||||
$app->load(__DIR__, $filename);
|
||||
$app->start();
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Core;
|
||||
|
||||
class Curl
|
||||
{
|
||||
@ -8,7 +8,7 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Core;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
@ -8,14 +8,18 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
use Exception;
|
||||
use Socket\Raw\Factory;
|
||||
|
||||
class TcpClient
|
||||
class AloneTcpClient
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
private static $heart_lock = 0;
|
||||
private static $client = null;
|
||||
private static $server_addr = null;
|
||||
@ -23,11 +27,11 @@ class TcpClient
|
||||
private static $socket_timeout = 0;
|
||||
|
||||
/**
|
||||
* @desc 入口
|
||||
* @use 入口
|
||||
*/
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time() || getenv('USE_SERVER') == 'false') {
|
||||
if (self::getLock() > time() || getenv('USE_ALONE_SERVER') == 'false') {
|
||||
return;
|
||||
}
|
||||
self::init();
|
||||
@ -37,16 +41,16 @@ class TcpClient
|
||||
|
||||
|
||||
/**
|
||||
* @desc 初始化
|
||||
* @use 初始化
|
||||
*/
|
||||
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('推送服务器信息不完整, 请检查配置文件!');
|
||||
}
|
||||
if (!self::$server_addr || !self::$server_key) {
|
||||
self::$server_addr = getenv('SERVER_ADDR');
|
||||
self::$server_key = getenv('SERVER_KEY');
|
||||
self::$server_addr = getenv('ALONE_SERVER_ADDR');
|
||||
self::$server_key = getenv('ALONE_SERVER_KEY');
|
||||
}
|
||||
if (!self::$client) {
|
||||
self::openConnect();
|
||||
@ -55,7 +59,7 @@ class TcpClient
|
||||
|
||||
|
||||
/**
|
||||
* @desc 数据封装
|
||||
* @use 数据封装
|
||||
* @param $value
|
||||
* @param $fmt
|
||||
* @return string
|
||||
@ -68,7 +72,7 @@ class TcpClient
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 数据解包
|
||||
* @use 数据解包
|
||||
* @param $value
|
||||
* @param string $fmt
|
||||
* @return array|false
|
||||
@ -80,7 +84,7 @@ class TcpClient
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 连接认证
|
||||
* @use 连接认证
|
||||
*/
|
||||
private static function handShake()
|
||||
{
|
||||
@ -96,7 +100,7 @@ class TcpClient
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 心跳
|
||||
* @use 心跳
|
||||
*/
|
||||
private static function heartBeat()
|
||||
{
|
||||
@ -109,7 +113,7 @@ class TcpClient
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 读数据
|
||||
* @use 读数据
|
||||
* @param $length
|
||||
* @return array|bool|false
|
||||
*/
|
||||
@ -132,7 +136,7 @@ class TcpClient
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 写数据
|
||||
* @use 写数据
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
@ -153,7 +157,7 @@ class TcpClient
|
||||
|
||||
|
||||
/**
|
||||
* @desc 打开连接
|
||||
* @use 打开连接
|
||||
*/
|
||||
private static function openConnect()
|
||||
{
|
||||
@ -166,13 +170,13 @@ class TcpClient
|
||||
Log::info("连接到 {$socket->getPeerName()} 推送服务器");
|
||||
} catch (Exception $e) {
|
||||
Log::error("连接到推送服务器失败, {$e->getMessage()}");
|
||||
self::$lock = time() + 60;
|
||||
self::setLock( 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 重新连接
|
||||
* @use 重新连接
|
||||
*/
|
||||
private static function reConnect()
|
||||
{
|
||||
@ -182,7 +186,7 @@ class TcpClient
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 断开连接
|
||||
* @use 断开连接
|
||||
*/
|
||||
private static function closeConnect()
|
||||
{
|
||||
@ -8,15 +8,18 @@
|
||||
* 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_SWITCH = 'USE_ANCHOR';
|
||||
|
||||
public static $lock = 0;
|
||||
public static $rw_lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
protected static $wait_list = [];
|
||||
protected static $finish_list = [];
|
||||
@ -24,41 +27,45 @@ class Anchor extends BaseRaffle
|
||||
|
||||
private static $filter_type = [];
|
||||
|
||||
|
||||
/**
|
||||
* 检查抽奖列表
|
||||
* @param $rid
|
||||
* @use 解析数据
|
||||
* @param int $room_id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
protected static function check($rid): bool
|
||||
protected static function parse(int $room_id, array $data): bool
|
||||
{
|
||||
$payload = [
|
||||
'roomid' => $rid
|
||||
];
|
||||
$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']) {
|
||||
// 防止异常
|
||||
if (!array_key_exists('anchor', $data['data'])) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// 去重
|
||||
if (self::toRepeatLid($de_raw['id'])) {
|
||||
return false;
|
||||
}
|
||||
// 推入列表
|
||||
$data = [
|
||||
'room_id' => $de_raw['data']['room_id'],
|
||||
'raffle_id' => $de_raw['data']['id'],
|
||||
'prize' => $de_raw['data']['award_name'],
|
||||
'wait' => strtotime(date("Y-m-d H:i:s"))
|
||||
'room_id' => $room_id,
|
||||
'raffle_id' => $de_raw['id'],
|
||||
'raffle_name' => $de_raw['award_name'],
|
||||
'wait' => time()
|
||||
];
|
||||
if (static::toRepeatLid($data['raffle_id'])) {
|
||||
return false;
|
||||
}
|
||||
Statistics::addPushList(static::ACTIVE_TITLE);
|
||||
array_push(static::$wait_list, $data);
|
||||
Statistics::addPushList(self::ACTIVE_TITLE);
|
||||
array_push(self::$wait_list, $data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -84,11 +91,10 @@ class Anchor extends BaseRaffle
|
||||
$de_raw = json_decode($raw, true);
|
||||
|
||||
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
|
||||
print_r($de_raw);
|
||||
Statistics::addSuccessList(static::ACTIVE_TITLE);
|
||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$data['prize']}");
|
||||
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$data['raffle_name']}");
|
||||
} 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;
|
||||
}
|
||||
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
|
||||
*/
|
||||
|
||||
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()
|
||||
{
|
||||
if (self::$lock > time() || getenv('USE_DANMU') == 'false') {
|
||||
if (self::getLock() > time() || getenv('USE_DANMU') == 'false') {
|
||||
return;
|
||||
}
|
||||
$room_id = empty(getenv('DANMU_ROOMID')) ? Live::getUserRecommend() : Live::getRealRoomID(getenv('DANMU_ROOMID'));
|
||||
@ -28,14 +32,18 @@ class Danmu
|
||||
];
|
||||
|
||||
if (self::privateSendMsg($info)) {
|
||||
self::$lock = time() + 3600;
|
||||
self::setLock(3600);
|
||||
return;
|
||||
}
|
||||
|
||||
self::$lock = time() + 30;
|
||||
self::setLock(30);
|
||||
}
|
||||
|
||||
// 获取随机弹幕
|
||||
|
||||
/**
|
||||
* @use 获取随机弹幕
|
||||
* @return \Exception|false|mixed|string
|
||||
*/
|
||||
private static function getMsgInfo()
|
||||
{
|
||||
/**
|
||||
@ -80,7 +88,11 @@ class Danmu
|
||||
}
|
||||
|
||||
|
||||
//发送弹幕通用模块
|
||||
/**
|
||||
* @use 弹幕通用模块
|
||||
* @param $info
|
||||
* @return bool|string
|
||||
*/
|
||||
private static function sendMsg($info)
|
||||
{
|
||||
$user_info = User::parseCookies();
|
||||
@ -101,24 +113,26 @@ class Danmu
|
||||
return Curl::post('https://api.live.bilibili.com/msg/send', Sign::api($payload));
|
||||
}
|
||||
|
||||
//使用发送弹幕模块
|
||||
/**
|
||||
* @use 发送弹幕模块
|
||||
* @param $info
|
||||
* @return bool
|
||||
*/
|
||||
private static function privateSendMsg($info)
|
||||
{
|
||||
//TODO 暂时性功能 有需求就修改
|
||||
$raw = self::sendMsg($info);
|
||||
$de_raw = json_decode($raw, true);
|
||||
|
||||
if ($de_raw['code'] == 1001) {
|
||||
Log::warning($de_raw['msg']);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$de_raw['code']) {
|
||||
Log::info('弹幕发送成功!');
|
||||
Log::info('活跃弹幕发送成功!');
|
||||
return true;
|
||||
}
|
||||
Log::error("活跃弹幕发送失败!, {$de_raw['msg']}");
|
||||
|
||||
Log::error("弹幕发送失败, {$de_raw['msg']}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -9,16 +9,16 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
|
||||
abstract class BaseRaffle
|
||||
{
|
||||
const ACTIVE_TITLE = '';
|
||||
const ACTIVE_SWITCH = '';
|
||||
|
||||
public static $lock;
|
||||
public static $rw_lock;
|
||||
|
||||
protected static $wait_list;
|
||||
protected static $finish_list;
|
||||
protected static $all_list;
|
||||
@ -28,29 +28,34 @@ abstract class BaseRaffle
|
||||
if (getenv(static::ACTIVE_SWITCH) == 'false') {
|
||||
return;
|
||||
}
|
||||
if (static::$lock > time()) {
|
||||
if (static::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
static::startLottery();
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽奖逻辑
|
||||
* @use 抽奖逻辑
|
||||
* @return bool
|
||||
*/
|
||||
protected static function startLottery(): bool
|
||||
{
|
||||
$max_num = mt_rand(10, 20);
|
||||
|
||||
if (count(static::$wait_list) == 0) {
|
||||
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');
|
||||
for ($i = 0; $i <= $max_num; $i++) {
|
||||
$raffle = array_shift(static::$wait_list);
|
||||
if (is_null($raffle)) {
|
||||
break;
|
||||
}
|
||||
if ($raffle['wait'] > strtotime(date("Y-m-d H:i:s"))) {
|
||||
if ($raffle['wait'] > time()) {
|
||||
array_push(static::$wait_list, $raffle);
|
||||
continue;
|
||||
}
|
||||
@ -61,13 +66,34 @@ abstract class BaseRaffle
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查抽奖列表
|
||||
* @param $rid
|
||||
* @use 解析抽奖数据
|
||||
* @param int $room_id
|
||||
* @param array $data
|
||||
* @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
|
||||
|
||||
|
||||
/**
|
||||
* 重复检测
|
||||
* @param int $lid
|
||||
* @use 去重检测
|
||||
* @param $lid
|
||||
* @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)) {
|
||||
return true;
|
||||
}
|
||||
@ -113,12 +140,11 @@ abstract class BaseRaffle
|
||||
static::$all_list = [];
|
||||
}
|
||||
array_push(static::$all_list, $lid);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据推入队列
|
||||
* @use 数据推入队列
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
@ -131,9 +157,12 @@ abstract class BaseRaffle
|
||||
if (Live::fishingDetection($data['rid'])) {
|
||||
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);
|
||||
if ($wait_num > 2) {
|
||||
if ($wait_num > 4 && ($wait_num % 2)) {
|
||||
Log::info("当前队列中共有 {$wait_num} 个" . static::ACTIVE_TITLE . "待抽奖");
|
||||
}
|
||||
return true;
|
||||
@ -8,23 +8,29 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class Daily
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
self::dailyBag();
|
||||
|
||||
self::$lock = time() + 3600;
|
||||
self::setLock( 8 * 60 * 60);
|
||||
}
|
||||
|
||||
protected static function dailyBag()
|
||||
/**
|
||||
* @use 领取每日包裹
|
||||
*/
|
||||
private static function dailyBag()
|
||||
{
|
||||
$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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class DataTreating
|
||||
{
|
||||
// TODO 独立分发 Push||Pull数据
|
||||
/**
|
||||
* @desc 抽奖分发
|
||||
* @use 抽奖分发
|
||||
* @param array $data
|
||||
*/
|
||||
public static function distribute(array $data)
|
||||
@ -28,19 +33,19 @@ class DataTreating
|
||||
switch ($data['raffle_type']) {
|
||||
case "storm":
|
||||
// 风暴
|
||||
Storm::pushToQueue($info);
|
||||
StormRaffle::pushToQueue($info);
|
||||
break;
|
||||
case "raffle":
|
||||
// 礼物
|
||||
UnifyRaffle::pushToQueue($info);
|
||||
GiftRaffle::pushToQueue($info);
|
||||
break;
|
||||
case "guard":
|
||||
// 舰长
|
||||
Guard::pushToQueue($info);
|
||||
GuardRaffle::pushToQueue($info);
|
||||
break;
|
||||
case "small_tv":
|
||||
// 电视
|
||||
UnifyRaffle::pushToQueue($info);
|
||||
GiftRaffle::pushToQueue($info);
|
||||
break;
|
||||
case 'pk':
|
||||
// 乱斗
|
||||
@ -48,7 +53,7 @@ class DataTreating
|
||||
break;
|
||||
case 'anchor':
|
||||
// 天选时刻
|
||||
Anchor::pushToQueue($info);
|
||||
AnchorRaffle::pushToQueue($info);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -8,27 +8,34 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class GiftHeart
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
// RUN
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
if (self::giftheart()) {
|
||||
self::$lock = time() + 60 * 60;
|
||||
if (self::giftHeart()) {
|
||||
self::setLock(60 * 60);
|
||||
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 = [
|
||||
'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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class GroupSignIn
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
// RUN
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$groups = self::getGroupList();
|
||||
if (empty($groups)) {
|
||||
self::$lock = time() + 24 * 60 * 60;
|
||||
self::setLock(24 * 60 * 60);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -31,10 +34,14 @@ class GroupSignIn
|
||||
self::signInGroup($group);
|
||||
}
|
||||
|
||||
self::$lock = time() + 8 * 60 * 60;
|
||||
self::setLock(8 * 60 * 60);
|
||||
}
|
||||
|
||||
//GROUP LIST
|
||||
|
||||
/**
|
||||
* @use 获取友爱社列表
|
||||
* @return array
|
||||
*/
|
||||
protected static function getGroupList(): array
|
||||
{
|
||||
$payload = [];
|
||||
@ -48,7 +55,12 @@ class GroupSignIn
|
||||
return $de_raw['data']['list'];
|
||||
}
|
||||
|
||||
//SIGN IN
|
||||
|
||||
/**
|
||||
* @use 签到
|
||||
* @param array $groupInfo
|
||||
* @return bool
|
||||
*/
|
||||
protected static function signInGroup(array $groupInfo): bool
|
||||
{
|
||||
$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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class Heart
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::pc();
|
||||
self::mobile();
|
||||
|
||||
self::$lock = time() + 300;
|
||||
self::setLock(5 * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* @use pc端心跳
|
||||
*/
|
||||
protected static function pc()
|
||||
{
|
||||
$payload = [
|
||||
@ -41,6 +48,9 @@ class Heart
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @use 手机端心跳
|
||||
*/
|
||||
protected static function mobile()
|
||||
{
|
||||
$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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
use BiliHelper\Core\Config;
|
||||
|
||||
|
||||
class Login
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
public static function run()
|
||||
{
|
||||
if (self::getLock()) {
|
||||
self::check();
|
||||
return;
|
||||
}
|
||||
Log::info('开始启动程序...');
|
||||
if (getenv('ACCESS_TOKEN') == "") {
|
||||
Log::info('令牌载入中...');
|
||||
self::login();
|
||||
}
|
||||
// 重载配置文件
|
||||
Index::$dotenv->overload();
|
||||
|
||||
Log::info('正在检查令牌合法性...');
|
||||
if (!self::info()) {
|
||||
@ -32,15 +40,19 @@ class Login
|
||||
self::login();
|
||||
}
|
||||
}
|
||||
self::$lock = time() + 3600;
|
||||
self::setLock(3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* @use 检查令牌
|
||||
* @return bool
|
||||
*/
|
||||
public static function check()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return true;
|
||||
}
|
||||
self::$lock = time() + 7200;
|
||||
self::setLock(7200);
|
||||
if (!self::info()) {
|
||||
Log::warning('令牌即将过期');
|
||||
Log::info('申请更换令牌中...');
|
||||
@ -53,6 +65,10 @@ class Login
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @use 获取令牌信息
|
||||
* @return bool
|
||||
*/
|
||||
protected static function info()
|
||||
{
|
||||
$access_token = getenv('ACCESS_TOKEN');
|
||||
@ -69,6 +85,10 @@ class Login
|
||||
return $data['data']['expires_in'] > 14400;
|
||||
}
|
||||
|
||||
/**
|
||||
* @use 刷新token
|
||||
* @return bool
|
||||
*/
|
||||
public static function refresh()
|
||||
{
|
||||
$access_token = getenv('ACCESS_TOKEN');
|
||||
@ -85,14 +105,19 @@ class Login
|
||||
}
|
||||
Log::info('令牌生成完毕!');
|
||||
$access_token = $data['data']['access_token'];
|
||||
File::writeNewEnvironmentFileWith('ACCESS_TOKEN', $access_token);
|
||||
Config::put('ACCESS_TOKEN', $access_token);
|
||||
Log::info(' > access token: ' . $access_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);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @use 普通登陆
|
||||
* @param string $captcha
|
||||
* @param array $headers
|
||||
*/
|
||||
protected static function login($captcha = '', $headers = [])
|
||||
{
|
||||
$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 = json_decode($data, true);
|
||||
if (isset($data['code']) && $data['code'] == -105) {
|
||||
$captcha_data = static::loginWithCaptcha();
|
||||
$captcha_data = self::loginWithCaptcha();
|
||||
$captcha = $captcha_data['captcha'];
|
||||
$headers = $captcha_data['headers'];
|
||||
continue;
|
||||
@ -148,16 +173,20 @@ class Login
|
||||
self::saveCookie($data);
|
||||
Log::info('令牌获取成功!');
|
||||
$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);
|
||||
$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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @use 验证码登陆
|
||||
* @return array
|
||||
*/
|
||||
protected static function loginWithCaptcha()
|
||||
{
|
||||
Log::info('登录需要验证, 启动验证码登录!');
|
||||
@ -169,7 +198,7 @@ class Login
|
||||
];
|
||||
$data = Curl::other('https://passport.bilibili.com/captcha', null, $headers);
|
||||
$data = base64_encode($data);
|
||||
$captcha = static::ocrCaptcha($data);
|
||||
$captcha = self::ocrCaptcha($data);
|
||||
return [
|
||||
'captcha' => $captcha,
|
||||
'headers' => $headers,
|
||||
@ -177,6 +206,11 @@ class Login
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @use 识别验证码
|
||||
* @param $captcha_img
|
||||
* @return mixed
|
||||
*/
|
||||
private static function ocrCaptcha($captcha_img)
|
||||
{
|
||||
$payload = [
|
||||
@ -192,6 +226,10 @@ class Login
|
||||
return $de_raw['message'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @use 保存cookie
|
||||
* @param $data
|
||||
*/
|
||||
private static function saveCookie($data)
|
||||
{
|
||||
Log::info('COOKIE获取成功!');
|
||||
@ -201,7 +239,7 @@ class Login
|
||||
foreach ($cookies as $cookie) {
|
||||
$temp .= $cookie['name'] . '=' . $cookie['value'] . ';';
|
||||
}
|
||||
File::writeNewEnvironmentFileWith('COOKIE', $temp);
|
||||
Config::put('COOKIE', $temp);
|
||||
Log::info(' > auth cookie: ' . $temp);
|
||||
return;
|
||||
}
|
||||
@ -8,25 +8,34 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class MasterSite
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time() || getenv('USE_MASTER_SITE') == 'false') {
|
||||
if (self::getLock() > time() || getenv('USE_MASTER_SITE') == 'false') {
|
||||
return;
|
||||
}
|
||||
if (self::watchAid() && self::shareAid() && self::coinAdd()) {
|
||||
self::$lock = time() + 24 * 60 * 60;
|
||||
self::setLock( 24 * 60 * 60);
|
||||
return;
|
||||
}
|
||||
self::$lock = time() + 3600;
|
||||
self::setLock( 3600);
|
||||
}
|
||||
|
||||
// 投币
|
||||
|
||||
/**
|
||||
* @use 投币
|
||||
* @param $aid
|
||||
* @return bool
|
||||
*/
|
||||
private static function reward($aid): bool
|
||||
{
|
||||
$user_info = User::parseCookies();
|
||||
@ -54,7 +63,11 @@ class MasterSite
|
||||
}
|
||||
}
|
||||
|
||||
// 投币日志
|
||||
|
||||
/**
|
||||
* @use 投币日志
|
||||
* @return int
|
||||
*/
|
||||
protected static function coinLog(): int
|
||||
{
|
||||
$url = "https://api.bilibili.com/x/member/web/coin/log";
|
||||
@ -87,7 +100,12 @@ class MasterSite
|
||||
return $coins;
|
||||
}
|
||||
|
||||
// 投币操作
|
||||
|
||||
/**
|
||||
* @use 投币视频
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected static function coinAdd(): bool
|
||||
{
|
||||
switch (getenv('USE_ADD_COIN')) {
|
||||
@ -123,7 +141,11 @@ class MasterSite
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取随机AID
|
||||
|
||||
/**
|
||||
* @use 获取随机AID
|
||||
* @return string
|
||||
*/
|
||||
private static function getRandomAid(): string
|
||||
{
|
||||
do {
|
||||
@ -139,7 +161,13 @@ class MasterSite
|
||||
return (string)$aid;
|
||||
}
|
||||
|
||||
// 日榜AID
|
||||
|
||||
/**
|
||||
* @use 获取日榜AID
|
||||
* @param $num
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function getDayRankingAids($num): array
|
||||
{
|
||||
// day: 日榜1 三榜3 周榜7 月榜30
|
||||
@ -166,7 +194,11 @@ class MasterSite
|
||||
return $aids;
|
||||
}
|
||||
|
||||
// 分享视频
|
||||
|
||||
/**
|
||||
* @use 分享视频
|
||||
* @return bool
|
||||
*/
|
||||
private static function shareAid(): bool
|
||||
{
|
||||
# aid = 稿件av号
|
||||
@ -195,7 +227,11 @@ class MasterSite
|
||||
}
|
||||
}
|
||||
|
||||
// 观看视频
|
||||
|
||||
/**
|
||||
* @use 观看视频
|
||||
* @return bool
|
||||
*/
|
||||
private static function watchAid(): bool
|
||||
{
|
||||
$url = "https://api.bilibili.com/x/report/click/h5";
|
||||
@ -259,7 +295,11 @@ class MasterSite
|
||||
return false;
|
||||
}
|
||||
|
||||
// 解析AID到CID
|
||||
|
||||
/**
|
||||
* @use 解析AID到CID
|
||||
* @return array
|
||||
*/
|
||||
private static function parseAid(): array
|
||||
{
|
||||
while (true) {
|
||||
@ -8,32 +8,33 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class MaterialObject
|
||||
{
|
||||
// 时间锁
|
||||
public static $lock = 0;
|
||||
// 丢弃列表
|
||||
use TimeLock;
|
||||
|
||||
private static $discard_aid_list = [];
|
||||
// 起始 和 结束
|
||||
private static $start_aid = 0;
|
||||
private static $end_aid = 0;
|
||||
|
||||
// RUN
|
||||
public static function run()
|
||||
{
|
||||
if (getenv('USE_MO') == 'false') {
|
||||
return;
|
||||
}
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
// 计算AID TODO 待优化
|
||||
self::calculateAid(150, 550);
|
||||
self::drawLottery();
|
||||
|
||||
self::$lock = time() + random_int(5, 10) * 60;
|
||||
self::setLock(random_int(5, 10) * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +45,7 @@ class MaterialObject
|
||||
{
|
||||
$block_key_list = ['测试', '加密', 'test', 'TEST', '钓鱼', '炸鱼', '调试'];
|
||||
$flag = 5;
|
||||
|
||||
|
||||
for ($i = self::$start_aid; $i < self::$end_aid; $i++) {
|
||||
if (!$flag) {
|
||||
break;
|
||||
@ -125,11 +126,13 @@ class MaterialObject
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @use 计算 开始结束的AID
|
||||
* @use 计算开始结束的AID
|
||||
* @param $min
|
||||
* @param $max
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
|
||||
class PkRaffle extends BaseRaffle
|
||||
{
|
||||
const ACTIVE_TITLE = '大乱斗';
|
||||
const ACTIVE_SWITCH = 'USE_PK';
|
||||
|
||||
public static $lock = 0;
|
||||
public static $rw_lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
protected static $wait_list = [];
|
||||
protected static $finish_list = [];
|
||||
protected static $all_list = [];
|
||||
|
||||
|
||||
/**
|
||||
* 检查抽奖列表
|
||||
* @param $rid
|
||||
* @use 解析数据
|
||||
* @param int $room_id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
protected static function check($rid): bool
|
||||
protected static function parse(int $room_id, array $data): bool
|
||||
{
|
||||
$payload = [
|
||||
'roomid' => $rid
|
||||
];
|
||||
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v1/pk/check';
|
||||
$raw = Curl::get($url, Sign::api($payload));
|
||||
$de_raw = json_decode($raw, true);
|
||||
|
||||
// 计数 && 跳出
|
||||
$total = count($de_raw['data']);
|
||||
if (!$total) {
|
||||
// 防止异常
|
||||
if (!array_key_exists('pk', $data['data'])) {
|
||||
return false;
|
||||
}
|
||||
$de_raw = $data['data']['pk'];
|
||||
if (empty($de_raw)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $total; $i++) {
|
||||
$data = [
|
||||
'raffle_id' => $de_raw['data'][$i]['pk_id'],
|
||||
'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'])) {
|
||||
foreach ($de_raw as $pk) {
|
||||
// 无效抽奖
|
||||
if ($pk['status'] != 1) {
|
||||
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;
|
||||
}
|
||||
@ -83,10 +91,10 @@ class PkRaffle extends BaseRaffle
|
||||
* {"code":-403,"data":null,"message":"访问被拒绝","msg":"访问被拒绝"}
|
||||
*/
|
||||
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
|
||||
Statistics::addSuccessList(static::ACTIVE_TITLE);
|
||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . static::ACTIVE_TITLE . ": {$de_raw['data']['award_text']}");
|
||||
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['data']['award_text']}");
|
||||
Statistics::addSuccessList(self::ACTIVE_TITLE);
|
||||
} 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;
|
||||
}
|
||||
@ -8,10 +8,19 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class Sign
|
||||
{
|
||||
/**
|
||||
* @use 计算sign
|
||||
* @param $payload
|
||||
* @return array
|
||||
*/
|
||||
public static function api($payload)
|
||||
{
|
||||
# iOS 6680
|
||||
@ -8,61 +8,34 @@
|
||||
* Updated: 2019 ~ 2020
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class Silver
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
protected static $task = [];
|
||||
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty(self::$task)) {
|
||||
self::pushTask();
|
||||
if (empty(self::$task)) {
|
||||
self::getSilverBox();
|
||||
} else {
|
||||
self::pullTask();
|
||||
self::openSilverBox();
|
||||
}
|
||||
}
|
||||
|
||||
protected static function pushTask()
|
||||
{
|
||||
$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::$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()
|
||||
/**
|
||||
* @use 获取宝箱
|
||||
*/
|
||||
private static function getSilverBox()
|
||||
{
|
||||
$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) {
|
||||
Log::notice($data['message']);
|
||||
self::$lock = time() + 24 * 60 * 60;
|
||||
self::setLock( 24 * 60 * 60);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,7 +59,44 @@ class Silver
|
||||
'time_start' => $data['data']['time_start'],
|
||||
'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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class Silver2Coin
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time() || getenv('USE_SILVER2COIN') == 'false') {
|
||||
if (self::getLock() > time() || getenv('USE_SILVER2COIN') == 'false') {
|
||||
return;
|
||||
}
|
||||
if (self::appSilver2coin() && self::pcSilver2coin()) {
|
||||
self::$lock = time() + 24 * 60 * 60;
|
||||
self::setLock(24 * 60 * 60);
|
||||
return;
|
||||
}
|
||||
self::$lock = time() + 3600;
|
||||
self::setLock(3600);
|
||||
}
|
||||
|
||||
|
||||
// APP API
|
||||
/**
|
||||
* @use app兑换
|
||||
* @return bool
|
||||
*/
|
||||
protected static function appSilver2coin(): bool
|
||||
{
|
||||
sleep(1);
|
||||
@ -46,14 +53,18 @@ class Silver2Coin
|
||||
return true;
|
||||
}
|
||||
|
||||
// PC API
|
||||
|
||||
/**
|
||||
* @use pc兑换
|
||||
* @return bool
|
||||
*/
|
||||
protected static function pcSilver2coin(): bool
|
||||
{
|
||||
sleep(1);
|
||||
$payload = [];
|
||||
$url = "https://api.live.bilibili.com/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));
|
||||
$de_raw = json_decode($raw, true);
|
||||
if ($de_raw['code'] == -403) {
|
||||
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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
|
||||
class Statistics
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
// 推送 参加 成功
|
||||
private static $push_list = [];
|
||||
private static $join_list = [];
|
||||
private static $success_list = [];
|
||||
|
||||
|
||||
// 日志
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
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
|
||||
{
|
||||
// 初始化三个必要值
|
||||
@ -47,22 +52,36 @@ class Statistics
|
||||
return true;
|
||||
}
|
||||
|
||||
// 添加参与
|
||||
|
||||
/**
|
||||
* @use 添加参与
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function addJoinList(string $key): bool
|
||||
{
|
||||
array_push(self::$join_list[$key], 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 添加成功
|
||||
|
||||
/**
|
||||
* @use 添加成功
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function addSuccessList(string $key): bool
|
||||
{
|
||||
array_push(self::$success_list[$key], 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取结果
|
||||
private static function getStormResult(): bool
|
||||
|
||||
/**
|
||||
* @use 输出结果
|
||||
* @return bool
|
||||
*/
|
||||
private static function outputResult(): bool
|
||||
{
|
||||
if (empty(self::$push_list)) {
|
||||
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
|
||||
*/
|
||||
|
||||
namespace lkeme\BiliHelper;
|
||||
namespace BiliHelper\Plugin;
|
||||
|
||||
use BiliHelper\Core\Log;
|
||||
use BiliHelper\Core\Curl;
|
||||
use BiliHelper\Util\TimeLock;
|
||||
|
||||
class Task
|
||||
{
|
||||
public static $lock = 0;
|
||||
use TimeLock;
|
||||
|
||||
public static function run()
|
||||
{
|
||||
if (self::$lock > time()) {
|
||||
if (self::getLock() > time()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log::info('正在检查每日任务...');
|
||||
|
||||
$data = self::check();
|
||||
|
||||
if (isset($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::$lock = time() + 3600;
|
||||
self::setLock(8 * 60 * 60);
|
||||
}
|
||||
|
||||
protected static function check()
|
||||
/**
|
||||
* @use 检查每日任务
|
||||
* @return bool|mixed|string
|
||||
*/
|
||||
private static function check()
|
||||
{
|
||||
$payload = [];
|
||||
$data = Curl::get('https://api.live.bilibili.com/i/api/taskInfo', Sign::api($payload));
|
||||
$data = json_decode($data, true);
|
||||
|
||||
Log::info('正在检查每日任务...');
|
||||
if (isset($data['code']) && $data['code']) {
|
||||
Log::warning('每日任务检查失败!', ['msg' => $data['message']]);
|
||||
}
|
||||
@ -47,7 +52,11 @@ class Task
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected static function sign_info($info)
|
||||
/**
|
||||
* @use 每日签到
|
||||
* @param $info
|
||||
*/
|
||||
private static function sign_info($info)
|
||||
{
|
||||
Log::info('检查任务「每日签到」...');
|
||||
|
||||
@ -65,11 +74,15 @@ class Task
|
||||
} else {
|
||||
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('检查任务「双端观看直播」...');
|
||||
|
||||
@ -77,12 +90,10 @@ class Task
|
||||
Log::notice('已经领取奖励');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($info['mobile_watch'] != 1 || $info['web_watch'] != 1) {
|
||||
Log::notice('任务未完成,请等待');
|
||||
return;
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'task_id' => 'double_watch_task',
|
||||
];
|
||||
@ -8,16 +8,22 @@
|
||||
* 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
|
||||
{
|
||||
// RUN
|
||||
public static function run()
|
||||
{
|
||||
}
|
||||
|
||||
// 实名检测
|
||||
|
||||
/**
|
||||
* @use 实名检测
|
||||
* @return bool
|
||||
*/
|
||||
public static function realNameCheck(): bool
|
||||
{
|
||||
$payload = [];
|
||||
@ -30,7 +36,11 @@ class User
|
||||
return true;
|
||||
}
|
||||
|
||||
// 老爷检测
|
||||
|
||||
/**
|
||||
* @use 是否是老爷
|
||||
* @return bool
|
||||
*/
|
||||
public static function isMaster(): bool
|
||||
{
|
||||
$payload = [
|
||||
@ -46,7 +56,11 @@ class User
|
||||
return false;
|
||||
}
|
||||
|
||||
// 用户名写入
|
||||
|
||||
/**
|
||||
* @use 用户名写入
|
||||
* @return bool
|
||||
*/
|
||||
public static function userInfo(): bool
|
||||
{
|
||||
$payload = [
|
||||
@ -59,13 +73,17 @@ class User
|
||||
return true;
|
||||
}
|
||||
if ($de_raw['msg'] == 'ok') {
|
||||
File::writeNewEnvironmentFileWith('APP_UNAME', $de_raw['data']['uname']);
|
||||
Config::put('APP_UNAME', $de_raw['data']['uname']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//转换信息
|
||||
|
||||
/**
|
||||
* @use 转换信息
|
||||
* @return array
|
||||
*/
|
||||
public static function parseCookies(): array
|
||||
{
|
||||
$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