From 44e54d38a8d2d8b9a44c12da389eda2695a3efeb Mon Sep 17 00:00:00 2001
From: Lkeme <19500576+lkeme@users.noreply.github.com>
Date: Fri, 27 Dec 2019 02:19:57 +0800
Subject: [PATCH] [update] Version 0.1.0
---
CHANGELOG.md | 70 +--
DOC.md | 78 ++--
README.md | 2 +-
composer.json | 8 +-
composer.lock | 88 +++-
conf/user.conf.example | 71 +--
index.php | 85 +---
src/File.php | 31 --
src/GiftSend.php | 112 -----
src/Guard.php | 124 -----
src/Live.php | 154 -------
src/Notice.php | 123 -----
src/Socket.php | 193 --------
src/Storm.php | 201 ---------
src/UnifyRaffle.php | 155 -------
src/Websocket.php | 217 ---------
src/Winning.php | 68 ---
src/core/App.php | 72 +++
src/core/Config.php | 98 ++++
src/{ => core}/Curl.php | 2 +-
src/{ => core}/Log.php | 2 +-
.../AloneTcpClient.php} | 42 +-
src/{Anchor.php => plugin/AnchorRaffle.php} | 70 +--
src/plugin/AwardRecord.php | 135 ++++++
src/{Danmu.php => plugin/Barrage.php} | 40 +-
src/{ => plugin}/BaseRaffle.php | 65 ++-
src/{ => plugin}/Daily.php | 18 +-
src/{ => plugin}/DataTreating.php | 19 +-
src/{ => plugin}/GiftHeart.php | 25 +-
src/plugin/GiftRaffle.php | 102 +++++
src/plugin/GiftSend.php | 275 +++++++++++
src/{ => plugin}/GroupSignIn.php | 28 +-
src/plugin/GuardRaffle.php | 113 +++++
src/{ => plugin}/Heart.php | 18 +-
src/plugin/Live.php | 173 +++++++
src/{ => plugin}/Login.php | 66 ++-
src/{ => plugin}/MasterSite.php | 66 ++-
src/{ => plugin}/MaterialObject.php | 23 +-
src/plugin/Notice.php | 120 +++++
src/{ => plugin}/PkRaffle.php | 66 +--
src/{ => plugin}/Sign.php | 11 +-
src/{ => plugin}/Silver.php | 96 ++--
src/{ => plugin}/Silver2Coin.php | 29 +-
src/plugin/Sleep.php | 80 ++++
src/{ => plugin}/Statistics.php | 43 +-
src/plugin/StormRaffle.php | 141 ++++++
src/{ => plugin}/Task.php | 39 +-
src/{ => plugin}/User.php | 38 +-
src/plugin/ZoneTcpClient.php | 427 ++++++++++++++++++
src/util/TimeLock.php | 38 ++
50 files changed, 2509 insertions(+), 1851 deletions(-)
delete mode 100644 src/File.php
delete mode 100644 src/GiftSend.php
delete mode 100644 src/Guard.php
delete mode 100644 src/Live.php
delete mode 100644 src/Notice.php
delete mode 100644 src/Socket.php
delete mode 100644 src/Storm.php
delete mode 100644 src/UnifyRaffle.php
delete mode 100644 src/Websocket.php
delete mode 100644 src/Winning.php
create mode 100644 src/core/App.php
create mode 100644 src/core/Config.php
rename src/{ => core}/Curl.php (99%)
rename src/{ => core}/Log.php (99%)
rename src/{TcpClient.php => plugin/AloneTcpClient.php} (89%)
rename src/{Anchor.php => plugin/AnchorRaffle.php} (55%)
create mode 100644 src/plugin/AwardRecord.php
rename src/{Danmu.php => plugin/Barrage.php} (83%)
rename src/{ => plugin}/BaseRaffle.php (65%)
rename src/{ => plugin}/Daily.php (69%)
rename src/{ => plugin}/DataTreating.php (72%)
rename src/{ => plugin}/GiftHeart.php (77%)
create mode 100644 src/plugin/GiftRaffle.php
create mode 100644 src/plugin/GiftSend.php
rename src/{ => plugin}/GroupSignIn.php (81%)
create mode 100644 src/plugin/GuardRaffle.php
rename src/{ => plugin}/Heart.php (81%)
create mode 100644 src/plugin/Live.php
rename src/{ => plugin}/Login.php (84%)
rename src/{ => plugin}/MasterSite.php (91%)
rename src/{ => plugin}/MaterialObject.php (94%)
create mode 100644 src/plugin/Notice.php
rename src/{ => plugin}/PkRaffle.php (62%)
rename src/{ => plugin}/Sign.php (85%)
rename src/{ => plugin}/Silver.php (74%)
rename src/{ => plugin}/Silver2Coin.php (75%)
create mode 100644 src/plugin/Sleep.php
rename src/{ => plugin}/Statistics.php (74%)
create mode 100644 src/plugin/StormRaffle.php
rename src/{ => plugin}/Task.php (80%)
rename src/{ => plugin}/User.php (81%)
create mode 100644 src/plugin/ZoneTcpClient.php
create mode 100644 src/util/TimeLock.php
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 703a1fd..9f28e14 100644
--- a/CHANGELOG.md
+++ b/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
diff --git a/DOC.md b/DOC.md
index 4951d9a..7b218da 100644
--- a/DOC.md
+++ b/DOC.md
@@ -2,7 +2,7 @@

-
+
@@ -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/sendMessage?chat_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 许可证
diff --git a/README.md b/README.md
index be6f22e..95357f1 100644
--- a/README.md
+++ b/README.md
@@ -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**
## 文档
diff --git a/composer.json b/composer.json
index eecd952..ded0d15 100644
--- a/composer.json
+++ b/composer.json
@@ -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"
}
}
}
diff --git a/composer.lock b/composer.lock
index 1c1c100..4093152 100644
--- a/composer.lock
+++ b/composer.lock
@@ -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": [],
diff --git a/conf/user.conf.example b/conf/user.conf.example
index 6e184c5..20ff895 100644
--- a/conf/user.conf.example
+++ b/conf/user.conf.example
@@ -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
+
+#######################
+# 程序设置 #
#######################
# 写入日志
diff --git a/index.php b/index.php
index 97479e6..3487d48 100644
--- a/index.php
+++ b/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();
diff --git a/src/File.php b/src/File.php
deleted file mode 100644
index 729955a..0000000
--- a/src/File.php
+++ /dev/null
@@ -1,31 +0,0 @@
- $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']}");
- }
- }
-}
diff --git a/src/Guard.php b/src/Guard.php
deleted file mode 100644
index e7b5c01..0000000
--- a/src/Guard.php
+++ /dev/null
@@ -1,124 +0,0 @@
- 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;
- }
-}
\ No newline at end of file
diff --git a/src/Live.php b/src/Live.php
deleted file mode 100644
index 154457b..0000000
--- a/src/Live.php
+++ /dev/null
@@ -1,154 +0,0 @@
- $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;
- }
-
-}
\ No newline at end of file
diff --git a/src/Notice.php b/src/Notice.php
deleted file mode 100644
index 7df86c4..0000000
--- a/src/Notice.php
+++ /dev/null
@@ -1,123 +0,0 @@
- '活动抽奖结果',
- '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);
- }
-}
\ No newline at end of file
diff --git a/src/Socket.php b/src/Socket.php
deleted file mode 100644
index abd7b29..0000000
--- a/src/Socket.php
+++ /dev/null
@@ -1,193 +0,0 @@
- 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;
- }
-}
\ No newline at end of file
diff --git a/src/Storm.php b/src/Storm.php
deleted file mode 100644
index 6fbf0a6..0000000
--- a/src/Storm.php
+++ /dev/null
@@ -1,201 +0,0 @@
- 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;
- }
-}
diff --git a/src/UnifyRaffle.php b/src/UnifyRaffle.php
deleted file mode 100644
index ba184e1..0000000
--- a/src/UnifyRaffle.php
+++ /dev/null
@@ -1,155 +0,0 @@
- $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;
- }
-}
diff --git a/src/Websocket.php b/src/Websocket.php
deleted file mode 100644
index 7a5d6d0..0000000
--- a/src/Websocket.php
+++ /dev/null
@@ -1,217 +0,0 @@
- 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;
- }
-}
\ No newline at end of file
diff --git a/src/Winning.php b/src/Winning.php
deleted file mode 100644
index b89bce8..0000000
--- a/src/Winning.php
+++ /dev/null
@@ -1,68 +0,0 @@
- 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;
- }
-}
\ No newline at end of file
diff --git a/src/core/App.php b/src/core/App.php
new file mode 100644
index 0000000..0603064
--- /dev/null
+++ b/src/core/App.php
@@ -0,0 +1,72 @@
+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;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Curl.php b/src/core/Curl.php
similarity index 99%
rename from src/Curl.php
rename to src/core/Curl.php
index adf87a5..86e9b4d 100644
--- a/src/Curl.php
+++ b/src/core/Curl.php
@@ -8,7 +8,7 @@
* Updated: 2019 ~ 2020
*/
-namespace lkeme\BiliHelper;
+namespace BiliHelper\Core;
class Curl
{
diff --git a/src/Log.php b/src/core/Log.php
similarity index 99%
rename from src/Log.php
rename to src/core/Log.php
index c6e663c..4dd8268 100644
--- a/src/Log.php
+++ b/src/core/Log.php
@@ -8,7 +8,7 @@
* Updated: 2019 ~ 2020
*/
-namespace lkeme\BiliHelper;
+namespace BiliHelper\Core;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
diff --git a/src/TcpClient.php b/src/plugin/AloneTcpClient.php
similarity index 89%
rename from src/TcpClient.php
rename to src/plugin/AloneTcpClient.php
index 5cafae9..073b626 100644
--- a/src/TcpClient.php
+++ b/src/plugin/AloneTcpClient.php
@@ -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()
{
diff --git a/src/Anchor.php b/src/plugin/AnchorRaffle.php
similarity index 55%
rename from src/Anchor.php
rename to src/plugin/AnchorRaffle.php
index ae6aa60..7b792d9 100644
--- a/src/Anchor.php
+++ b/src/plugin/AnchorRaffle.php
@@ -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;
}
diff --git a/src/plugin/AwardRecord.php b/src/plugin/AwardRecord.php
new file mode 100644
index 0000000..be60103
--- /dev/null
+++ b/src/plugin/AwardRecord.php
@@ -0,0 +1,135 @@
+ 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);
+ }
+}
\ No newline at end of file
diff --git a/src/Danmu.php b/src/plugin/Barrage.php
similarity index 83%
rename from src/Danmu.php
rename to src/plugin/Barrage.php
index c6172d1..e838858 100644
--- a/src/Danmu.php
+++ b/src/plugin/Barrage.php
@@ -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;
}
}
\ No newline at end of file
diff --git a/src/BaseRaffle.php b/src/plugin/BaseRaffle.php
similarity index 65%
rename from src/BaseRaffle.php
rename to src/plugin/BaseRaffle.php
index eb2b92c..5867548 100644
--- a/src/BaseRaffle.php
+++ b/src/plugin/BaseRaffle.php
@@ -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;
diff --git a/src/Daily.php b/src/plugin/Daily.php
similarity index 69%
rename from src/Daily.php
rename to src/plugin/Daily.php
index f3bf116..945b4e0 100644
--- a/src/Daily.php
+++ b/src/plugin/Daily.php
@@ -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));
diff --git a/src/DataTreating.php b/src/plugin/DataTreating.php
similarity index 72%
rename from src/DataTreating.php
rename to src/plugin/DataTreating.php
index b0ece70..ac18afe 100644
--- a/src/DataTreating.php
+++ b/src/plugin/DataTreating.php
@@ -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;
diff --git a/src/GiftHeart.php b/src/plugin/GiftHeart.php
similarity index 77%
rename from src/GiftHeart.php
rename to src/plugin/GiftHeart.php
index 35d3320..3b1f7e1 100644
--- a/src/GiftHeart.php
+++ b/src/plugin/GiftHeart.php
@@ -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'),
diff --git a/src/plugin/GiftRaffle.php b/src/plugin/GiftRaffle.php
new file mode 100644
index 0000000..284f196
--- /dev/null
+++ b/src/plugin/GiftRaffle.php
@@ -0,0 +1,102 @@
+ $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;
+ }
+}
diff --git a/src/plugin/GiftSend.php b/src/plugin/GiftSend.php
new file mode 100644
index 0000000..4165766
--- /dev/null
+++ b/src/plugin/GiftSend.php
@@ -0,0 +1,275 @@
+ 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']}");
+ }
+ }
+}
diff --git a/src/GroupSignIn.php b/src/plugin/GroupSignIn.php
similarity index 81%
rename from src/GroupSignIn.php
rename to src/plugin/GroupSignIn.php
index b7f4512..5452ba0 100644
--- a/src/GroupSignIn.php
+++ b/src/plugin/GroupSignIn.php
@@ -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 = [
diff --git a/src/plugin/GuardRaffle.php b/src/plugin/GuardRaffle.php
new file mode 100644
index 0000000..ca084d1
--- /dev/null
+++ b/src/plugin/GuardRaffle.php
@@ -0,0 +1,113 @@
+ $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;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/Heart.php b/src/plugin/Heart.php
similarity index 81%
rename from src/Heart.php
rename to src/plugin/Heart.php
index 889cc08..80092cc 100644
--- a/src/Heart.php
+++ b/src/plugin/Heart.php
@@ -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 = [
diff --git a/src/plugin/Live.php b/src/plugin/Live.php
new file mode 100644
index 0000000..8a806c3
--- /dev/null
+++ b/src/plugin/Live.php
@@ -0,0 +1,173 @@
+ $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);
+ }
+
+}
\ No newline at end of file
diff --git a/src/Login.php b/src/plugin/Login.php
similarity index 84%
rename from src/Login.php
rename to src/plugin/Login.php
index 12d470a..99855dd 100644
--- a/src/Login.php
+++ b/src/plugin/Login.php
@@ -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;
}
diff --git a/src/MasterSite.php b/src/plugin/MasterSite.php
similarity index 91%
rename from src/MasterSite.php
rename to src/plugin/MasterSite.php
index 88ad3dd..3ccd5c4 100644
--- a/src/MasterSite.php
+++ b/src/plugin/MasterSite.php
@@ -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) {
diff --git a/src/MaterialObject.php b/src/plugin/MaterialObject.php
similarity index 94%
rename from src/MaterialObject.php
rename to src/plugin/MaterialObject.php
index 412236d..400d372 100644
--- a/src/MaterialObject.php
+++ b/src/plugin/MaterialObject.php
@@ -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
{
diff --git a/src/plugin/Notice.php b/src/plugin/Notice.php
new file mode 100644
index 0000000..9a6be44
--- /dev/null
+++ b/src/plugin/Notice.php
@@ -0,0 +1,120 @@
+ '天选时刻获奖记录',
+ '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酱推送信息失败,请检查!');
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/PkRaffle.php b/src/plugin/PkRaffle.php
similarity index 62%
rename from src/PkRaffle.php
rename to src/plugin/PkRaffle.php
index c95549d..44d87e2 100644
--- a/src/PkRaffle.php
+++ b/src/plugin/PkRaffle.php
@@ -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;
}
diff --git a/src/Sign.php b/src/plugin/Sign.php
similarity index 85%
rename from src/Sign.php
rename to src/plugin/Sign.php
index 6ffc65e..af6f804 100644
--- a/src/Sign.php
+++ b/src/plugin/Sign.php
@@ -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
diff --git a/src/Silver.php b/src/plugin/Silver.php
similarity index 74%
rename from src/Silver.php
rename to src/plugin/Silver.php
index 8946a59..979a0e5 100644
--- a/src/Silver.php
+++ b/src/plugin/Silver.php
@@ -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);
}
}
diff --git a/src/Silver2Coin.php b/src/plugin/Silver2Coin.php
similarity index 75%
rename from src/Silver2Coin.php
rename to src/plugin/Silver2Coin.php
index f336c2f..8a8a4d4 100644
--- a/src/Silver2Coin.php
+++ b/src/plugin/Silver2Coin.php
@@ -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) {
diff --git a/src/plugin/Sleep.php b/src/plugin/Sleep.php
new file mode 100644
index 0000000..cb7a5c4
--- /dev/null
+++ b/src/plugin/Sleep.php
@@ -0,0 +1,80 @@
+ 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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Statistics.php b/src/plugin/Statistics.php
similarity index 74%
rename from src/Statistics.php
rename to src/plugin/Statistics.php
index ef8b4b4..ce3dd20 100644
--- a/src/Statistics.php
+++ b/src/plugin/Statistics.php
@@ -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;
diff --git a/src/plugin/StormRaffle.php b/src/plugin/StormRaffle.php
new file mode 100644
index 0000000..9c25b4f
--- /dev/null
+++ b/src/plugin/StormRaffle.php
@@ -0,0 +1,141 @@
+ $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;
+ }
+}
diff --git a/src/Task.php b/src/plugin/Task.php
similarity index 80%
rename from src/Task.php
rename to src/plugin/Task.php
index 39cf86f..be40306 100644
--- a/src/Task.php
+++ b/src/plugin/Task.php
@@ -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',
];
diff --git a/src/User.php b/src/plugin/User.php
similarity index 81%
rename from src/User.php
rename to src/plugin/User.php
index 4bbde7c..fc4b549 100644
--- a/src/User.php
+++ b/src/plugin/User.php
@@ -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');
diff --git a/src/plugin/ZoneTcpClient.php b/src/plugin/ZoneTcpClient.php
new file mode 100644
index 0000000..24c4d1e
--- /dev/null
+++ b/src/plugin/ZoneTcpClient.php
@@ -0,0 +1,427 @@
+ 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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/util/TimeLock.php b/src/util/TimeLock.php
new file mode 100644
index 0000000..41e9b4a
--- /dev/null
+++ b/src/util/TimeLock.php
@@ -0,0 +1,38 @@
+