Merge branch 'lkeme:master' into master

This commit is contained in:
DishesDog 2021-08-23 09:15:42 +08:00 committed by GitHub
commit afcb4d96ca
84 changed files with 2339 additions and 1000 deletions

2
.github/FUNDING.yml vendored
View File

@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://i.loli.net/2019/07/13/5d2963e5cc1eb22973.png']
custom: [ 'https://i.loli.net/2019/07/13/5d2963e5cc1eb22973.png' ]

View File

@ -1,5 +1,7 @@
# Issue: BiliHepler 程序问题
<!-- 上面是标题 下面才是正文 -->
### 版本、安装方式、系统
1. 你在使用什么版本的 BiliHelper
@ -10,22 +12,24 @@
3. 你所使用的操作系统
---
### 描述问题
<!-- 在下方简要描述问题 -->
---
### 复现问题的步骤
<!-- 在下方描述如何复现问题 -->
---
### BiliHelper 运行日志:
<!-- 如果条件允许请附日志 -->
```shell
@ -38,5 +42,6 @@
---
### 截图
<!-- 如果条件允许请附图 -->

View File

@ -1,5 +1,7 @@
# Issue: Bug Report
<!-- 上面是标题 下面才是正文 -->
### Version, approach of installation, operating system
1. What version of BiliHelper are you using?
@ -10,22 +12,24 @@
3. What is your operating system?
---
### Description
<!-- Describe your problem below -->
---
### Steps to reproduce
<!-- Describe how to reproduce problem below -->
---
### BiliHelper Logs
<!-- Paste log if possible -->
```shell
@ -38,5 +42,6 @@
---
### Screenshot
<!-- Paste screenshot if possible -->

4
.gitignore vendored
View File

@ -26,16 +26,16 @@ conf/user1.ini
/conf/user.ini
/conf/test.ini
/conf/test1.ini
/log/
/src/backup/
script.php
# ignore all files in lib/
task/*
cache/*
log/*
# except for .gitkeep
!.gitkeep
# ignore TODO file in root directory,not subdir/TODO
/TODO
/Todo
cache/*

View File

@ -8,6 +8,34 @@
[comment]: <> (</details>)
## v1.0.0.210822 alpha (2021-08-22)
### Added
- 支持自定义设备
- 全面支持PHP8.0
- 支持本地缓存
- 对使用体验进行了一轮优化并解决了一些bug~~
-
### Changed
- PHP版本提升值8.*, 不向下兼容
- 对使用体验进行了一轮优化并解决了一些bug~~
-
### Fixed
- 对使用体验进行了一轮优化并解决了一些bug~~
-
### Remarks
- 注意文档文件有些许改动
- 注意需要重新进行`composer update`操作
- 注意只支持PHP8.* 只支持PHP8.* 只支持PHP8.*
-
## v0.9.9.210807 alpha (2021-08-07)
### Added

48
DOC.md
View File

@ -18,7 +18,7 @@
|Requirement |
|--------------------|
|PHP >=7.3 |
|PHP >=8.0 |
|php_curl |
|php_sockets |
|php_openssl |
@ -36,7 +36,7 @@
+ 阿里云(全量镜像)
```bash
```shell script
# 使用帮助
> https://developer.aliyun.com/composer
# 使用命令
@ -45,7 +45,7 @@
+ 恢复默认镜像|Composer.phar加速下载
```bash
```shell script
> composer config -g --unset repos.packagist
> https://mirrors.cloud.tencent.com/composer/composer.phar
@ -56,7 +56,7 @@
<summary>其余镜像 展开查看</summary>
<pre><code>
+ cnpkg(全量镜像)
```bash
```shell script
# 使用帮助
> https://php.cnpkg.org/
# 使用命令
@ -65,16 +65,16 @@
+ 腾讯云(全量镜像)
```bash
```shell script
# 使用帮助
> https://mirrors.cloud.tencent.com/help/composer.html
# 使用命令
> composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/
```
+ phpcomposer(全量镜像)
+ PhpComposer(全量镜像)
```bash
```shell script
# 使用帮助
> https://pkg.phpcomposer.com/
# 使用命令
@ -83,7 +83,7 @@
+ 华为云(全量镜像)
```bash
```shell script
# 使用帮助
> https://mirrors.huaweicloud.com/repository/php/
# 使用命令
@ -92,7 +92,7 @@
+ 交通大学(非全量镜像)
```bash
```shell script
# 使用帮助
> https://packagist.mirrors.sjtug.sjtu.edu.cn/
# 使用命令
@ -106,7 +106,7 @@
1. 下载(克隆)项目代码,初始化项目
```
```shell script
$ git clone https://github.com/lkeme/BiliHelper-personal.git
$ cd BiliHelper-personal/conf
$ cp user.ini.example user.ini
@ -114,7 +114,7 @@ $ cp user.ini.example user.ini
2. 使用 [composer](https://getcomposer.org/download/) 工具进行安装
```
```shell script
$ composer install
```
@ -124,13 +124,14 @@ $ composer install
3. 按照说明修改配置文件 `user.ini`
```
```shell script
# 默认只需填写帐号密码,按需求开启其他功能即可
...
```
4. 运行测试
```
```shell script
$ php index.php
```
@ -138,11 +139,26 @@ $ php index.php
5. 复制一份example配置文件修改账号密码即可
```
```shell script
$ php index.php example.ini
```
6. 请保证配置文件存在,否则默认加载`user.ini`配置文件
6. 自定义设备方案
```shell script
$ cd conf
$ cp bili.yaml user_bili.yaml
$ cp device.yaml user_device.yaml
```
7. 命令模式
```shell script
# 获取所有命令
$ php index.php -?
```
8. 请保证配置文件存在,否则默认加载`user.ini`配置文件
<p align="center"><img width="680px" src="https://user-images.githubusercontent.com/19500576/118621472-f8455d80-b7f8-11eb-9fec-500148a566b4.png"></p>
@ -173,7 +189,7 @@ $ docker run -itd --rm -v /path/to/your/confFileName.ini:/app/conf/user.ini lkem
- 使用github镜像加速
```bash
```shell script
$ -e MIRRORS=0 # 使用 github.com
$ -e MIRRORS=1 # 使用 ghproxy.com
$ -e MIRRORS=2 # 使用 github.com.cnpmjs.org

View File

@ -16,7 +16,7 @@
<p align="center">
<img src="https://img.shields.io/badge/Version-0.9.9.210807-orange.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/Version-1.0.0.210822-orange.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/PHP-7.3+-green.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/Composer-latest-blueviolet.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/License-mit-blue.svg?longCache=true&style=for-the-badge">
@ -31,6 +31,7 @@
---- 免费的东西总是得不到人的珍惜。
---- 只有花大价钱去买到的东西,才会令人信任。
```
## 🖥️星图
[![Stargazers over time](https://starchart.cc/lkeme/BiliHelper-personal.svg)](https://starchart.cc/lkeme/BiliHelper-personal)
@ -42,45 +43,46 @@
| plugin | status | version | cycle | description |
|-----------------|--------|----------|--------|---------------------------------------------|
| CheckUpdate | true | 21.08.07 | 待整理 | 程序检查更新 |
| Login | true | 21.08.07 | 待整理 | 账号登录、刷新、维持 |
| Schedule | true | 21.08.07 | 待整理 | 控制插件运行周期 |
| MainSite | true | 21.08.07 | 待整理 | 投币、观看、分享视频 (速升6级不是梦) |
| DailyBag | true | 21.08.07 | 待整理 | 双端领取日常/周常礼包 |
| ManGa | true | 21.08.07 | 待整理 | 漫画签到、分享 |
| ActivityLottery | true | 21.08.07 | 待整理 | 主站活动九宫格抽奖 |
| Competition | true | 21.08.07 | 待整理 | 游戏赛事竞猜 |
| DoubleHeart | true | 21.08.07 | 待整理 | 双端心跳 (姥爷直播经验) |
| DailyTask | true | 21.08.07 | 待整理 | 直播每日任务(签到、观看) |
| Barrage | true | 21.08.07 | 待整理 | 保持活跃弹幕 |
| Silver2Coin | true | 21.08.07 | 待整理 | 银瓜子兑换硬币 |
| Judge | true | 21.08.07 | 待整理 | 风纪委员投票 |
| GiftSend | true | 21.08.07 | 待整理 | 礼物赠送、维持每日勋章亲密度 |
| GroupSignIn | true | 21.08.07 | 待整理 | 友爱社签到 |
| GiftHeart | true | 21.08.07 | 待整理 | 日常心跳每日礼包礼物 |
| SmallHeart | true | 21.08.07 | 待整理 | 直播挂机每日24个小心心 |
| MaterialObject | true | 21.08.07 | 待整理 | 直播金色宝箱实物抽奖 |
| AloneTcpClient | true | 21.08.07 | 待整理 | 作者的独立直播监控(可支持本项目哦) |
| ZoneTcpClient | true | 21.08.07 | 待整理 | 官方的分区直播监控 |
| StormRaffle | true | 21.08.07 | 待整理 | 直播节奏风暴抽奖、亿元 |
| GiftRaffle | true | 21.08.07 | 待整理 | 直播礼物抽奖 |
| PkRaffle | true | 21.08.07 | 待整理 | 直播大乱斗抽奖 |
| GuardRaffle | true | 21.08.07 | 待整理 | 直播大航海抽奖 |
| AnchorRaffle | true | 21.08.07 | 待整理 | 直播天选时刻抽奖 |
| GiftRaffle | true | 21.08.07 | 待整理 | 直播礼物抽奖 |
| AwardRecord | true | 21.08.07 | 待整理 | 最新的中奖纪录通知 |
| Forward | true | 21.08.07 | 待整理 | 主站动态抽奖转发 |
| CapsuleLottery | true | 21.08.07 | 待整理 | 直播扭蛋活动抽奖 |
| PolishTheMedal | true | 21.08.07 | 待整理 | 每日自动点亮灰色勋章 |
| CapsuleLottery | true | 21.08.07 | 待整理 | 直播扭蛋活动抽奖 |
| VipPrivilege | true | 21.08.07 | 待整理 | 每月领取年度大会员特权(B币券、会员购优惠券) |
| BpConsumption | true | 21.08.07 | 待整理 | 每月消费使用年度大会员特权的B币券 |
| Statistics | true | 21.08.07 | 待整理 | 全局抽奖结果统计 |
| CheckUpdate | true | 21.08.22 | 待整理 | 程序检查更新 |
| Login | true | 21.08.22 | 待整理 | 账号登录、刷新、维持 |
| Schedule | true | 21.08.22 | 待整理 | 控制插件运行周期 |
| MainSite | true | 21.08.22 | 待整理 | 投币、观看、分享视频 (速升6级不是梦) |
| DailyBag | true | 21.08.22 | 待整理 | 双端领取日常/周常礼包 |
| ManGa | true | 21.08.22 | 待整理 | 漫画签到、分享 |
| ActivityLottery | true | 21.08.22 | 待整理 | 主站活动九宫格抽奖 |
| Competition | true | 21.08.22 | 待整理 | 游戏赛事竞猜 |
| DoubleHeart | true | 21.08.22 | 待整理 | 双端心跳 (姥爷直播经验) |
| DailyTask | true | 21.08.22 | 待整理 | 直播每日任务(签到、观看) |
| Barrage | true | 21.08.22 | 待整理 | 保持活跃弹幕 |
| Silver2Coin | true | 21.08.22 | 待整理 | 银瓜子兑换硬币 |
| Judge | true | 21.08.22 | 待整理 | 风纪委员投票 |
| GiftSend | true | 21.08.22 | 待整理 | 礼物赠送、维持每日勋章亲密度 |
| GroupSignIn | true | 21.08.22 | 待整理 | 友爱社签到 |
| GiftHeart | true | 21.08.22 | 待整理 | 日常心跳每日礼包礼物 |
| SmallHeart | true | 21.08.22 | 待整理 | 直播挂机每日24个小心心 |
| MaterialObject | true | 21.08.22 | 待整理 | 直播金色宝箱实物抽奖 |
| AloneTcpClient | true | 21.08.22 | 待整理 | 作者的独立直播监控(可支持本项目哦) |
| ZoneTcpClient | true | 21.08.22 | 待整理 | 官方的分区直播监控 |
| StormRaffle | true | 21.08.22 | 待整理 | 直播节奏风暴抽奖、亿元 |
| GiftRaffle | true | 21.08.22 | 待整理 | 直播礼物抽奖 |
| PkRaffle | true | 21.08.22 | 待整理 | 直播大乱斗抽奖 |
| GuardRaffle | true | 21.08.22 | 待整理 | 直播大航海抽奖 |
| AnchorRaffle | true | 21.08.22 | 待整理 | 直播天选时刻抽奖 |
| GiftRaffle | true | 21.08.22 | 待整理 | 直播礼物抽奖 |
| AwardRecord | true | 21.08.22 | 待整理 | 最新的中奖纪录通知 |
| Forward | true | 21.08.22 | 待整理 | 主站动态抽奖转发 |
| CapsuleLottery | true | 21.08.22 | 待整理 | 直播扭蛋活动抽奖 |
| PolishTheMedal | true | 21.08.22 | 待整理 | 每日自动点亮灰色勋章 |
| CapsuleLottery | true | 21.08.22 | 待整理 | 直播扭蛋活动抽奖 |
| VipPrivilege | true | 21.08.22 | 待整理 | 每月领取年度大会员特权(B币券、会员购优惠券) |
| BpConsumption | true | 21.08.22 | 待整理 | 每月消费使用年度大会员特权的B币券 |
| Statistics | true | 21.08.22 | 待整理 | 全局抽奖结果统计 |
| Silver | false | 21.03.27 | 待整理 | 直播银瓜子自动开启宝箱 |
## 交流反馈
`没事不要加、潜水不要加、哑巴不要加。`
Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg) | **请不要来问如何使用, 文档齐全, 仅用于BUG提交反馈**
## 相关文档

3
cache/.gitkeep vendored Normal file
View File

@ -0,0 +1,3 @@
# Ignore everything in this directory
*
# Except this file !.gitkeep

View File

@ -3,7 +3,7 @@
"description": "B 站自动领瓜子、直播助手、直播挂机脚本、主站助手 - PHP 版Personal",
"type": "project",
"require": {
"php": ">=7.3.0",
"php": ">=8.0",
"ext-curl": "*",
"ext-openssl": "*",
"ext-sockets": "*",
@ -21,7 +21,9 @@
"hassankhan/config": "^2.2",
"lkeme/inifile": "^3.4",
"adhocore/cli": "^0.9.0",
"fire015/flintstone": "^2.3"
"fire015/flintstone": "^2.3",
"symfony/yaml": "^5.3",
"consolidation/config": "^2.0"
},
"license": "MIT",
"authors": [
@ -37,7 +39,8 @@
"BiliHelper\\Plugin\\": "src/plugin",
"BiliHelper\\Util\\": "src/util",
"BiliHelper\\Tool\\": "src/tool",
"BiliHelper\\Script\\": "src/script"
"BiliHelper\\Script\\": "src/script",
"BiliHelper\\Exceptions\\": "src/exception"
},
"files": [
"src/core/Helpers.php"

756
composer.lock generated
View File

@ -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": "28d262a352d5f6367f17a5e73ab48ade",
"content-hash": "503a15c08236b91de15913134d6f88e3",
"packages": [
{
"name": "adhocore/cli",
@ -350,6 +350,72 @@
],
"time": "2020-11-27T13:16:18+00:00"
},
{
"name": "consolidation/config",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/consolidation/config.git",
"reference": "9a2c2a7b2aea1b3525984a4378743a8b74c14e1c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/config/zipball/9a2c2a7b2aea1b3525984a4378743a8b74c14e1c",
"reference": "9a2c2a7b2aea1b3525984a4378743a8b74c14e1c",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"dflydev/dot-access-data": "^1.1.0",
"grasmash/expander": "^1",
"php": ">=7.1.3",
"psr/log": "^1.1",
"symfony/event-dispatcher": "^4||^5"
},
"require-dev": {
"phpunit/phpunit": ">=7.5.20",
"squizlabs/php_codesniffer": "^3",
"symfony/console": "^4||^5",
"symfony/yaml": "^4||^5",
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
"symfony/event-dispatcher": "Required to inject configuration into Command options",
"symfony/yaml": "Required to use Consolidation\\Config\\Loader\\YamlConfigLoader"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"Consolidation\\Config\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Greg Anderson",
"email": "greg.1.anderson@greenknowe.org"
}
],
"description": "Provide configuration services for a commandline tool.",
"support": {
"issues": "https://github.com/consolidation/config/issues",
"source": "https://github.com/consolidation/config/tree/2.0.1"
},
"time": "2020-12-06T00:03:30+00:00"
},
{
"name": "container-interop/container-interop",
"version": "1.2.0",
@ -392,6 +458,75 @@
"abandoned": "psr/container",
"time": "2017-02-14T19:40:03+00:00"
},
{
"name": "dflydev/dot-access-data",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/dflydev/dflydev-dot-access-data.git",
"reference": "3fbd874921ab2c041e899d044585a2ab9795df8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/3fbd874921ab2c041e899d044585a2ab9795df8a",
"reference": "3fbd874921ab2c041e899d044585a2ab9795df8a",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-0": {
"Dflydev\\DotAccessData": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dragonfly Development Inc.",
"email": "info@dflydev.com",
"homepage": "http://dflydev.com"
},
{
"name": "Beau Simensen",
"email": "beau@dflydev.com",
"homepage": "http://beausimensen.com"
},
{
"name": "Carlos Frutos",
"email": "carlos@kiwing.it",
"homepage": "https://github.com/cfrutos"
}
],
"description": "Given a deep data structure, access data by dot notation.",
"homepage": "https://github.com/dflydev/dflydev-dot-access-data",
"keywords": [
"access",
"data",
"dot",
"notation"
],
"support": {
"issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
"source": "https://github.com/dflydev/dflydev-dot-access-data/tree/master"
},
"time": "2017-01-20T21:14:22+00:00"
},
{
"name": "fire015/flintstone",
"version": "v2.3.0",
@ -449,6 +584,63 @@
},
"time": "2021-01-20T10:36:23+00:00"
},
{
"name": "grasmash/expander",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/grasmash/expander.git",
"reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/grasmash/expander/zipball/95d6037344a4be1dd5f8e0b0b2571a28c397578f",
"reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"dflydev/dot-access-data": "^1.1.0",
"php": ">=5.4"
},
"require-dev": {
"greg-1-anderson/composer-test-scenarios": "^1",
"phpunit/phpunit": "^4|^5.5.4",
"satooshi/php-coveralls": "^1.0.2|dev-master",
"squizlabs/php_codesniffer": "^2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Grasmash\\Expander\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matthew Grasmick"
}
],
"description": "Expands internal property references in PHP arrays file.",
"support": {
"issues": "https://github.com/grasmash/expander/issues",
"source": "https://github.com/grasmash/expander/tree/master"
},
"time": "2017-12-21T22:14:55+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.5.5",
@ -1357,6 +1549,62 @@
},
"time": "2021-03-05T17:36:06+00:00"
},
{
"name": "psr/event-dispatcher",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/event-dispatcher.git",
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\EventDispatcher\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Standard interfaces for event handling.",
"keywords": [
"events",
"psr",
"psr-14"
],
"support": {
"issues": "https://github.com/php-fig/event-dispatcher/issues",
"source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
},
"time": "2019-01-08T18:20:26+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
@ -1583,6 +1831,340 @@
},
"time": "2021-01-19T12:14:40+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-03-23T23:28:01+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v5.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "f2fd2208157553874560f3645d4594303058c4bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f2fd2208157553874560f3645d4594303058c4bd",
"reference": "f2fd2208157553874560f3645d4594303058c4bd",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/event-dispatcher-contracts": "^2",
"symfony/polyfill-php80": "^1.16"
},
"conflict": {
"symfony/dependency-injection": "<4.4"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
"symfony/event-dispatcher-implementation": "2.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/error-handler": "^4.4|^5.0",
"symfony/expression-language": "^4.4|^5.0",
"symfony/http-foundation": "^4.4|^5.0",
"symfony/service-contracts": "^1.1|^2",
"symfony/stopwatch": "^4.4|^5.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v5.3.4"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-07-23T15:55:36+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11",
"reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2.5",
"psr/event-dispatcher": "^1"
},
"suggest": {
"symfony/event-dispatcher-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\EventDispatcher\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to dispatching event",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-03-23T23:28:01+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.23.0",
@ -1847,6 +2429,176 @@
}
],
"time": "2021-05-27T09:17:38+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"files": [
"bootstrap.php"
],
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-07-28T13:41:28+00:00"
},
{
"name": "symfony/yaml",
"version": "v5.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "4500fe63dc9c6ffc32d3b1cb0448c329f9c814b7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/4500fe63dc9c6ffc32d3b1cb0448c329f9c814b7",
"reference": "4500fe63dc9c6ffc32d3b1cb0448c329f9c814b7",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"symfony/console": "<4.4"
},
"require-dev": {
"symfony/console": "^4.4|^5.0"
},
"suggest": {
"symfony/console": "For validating YAML files using the lint command"
},
"bin": [
"Resources/bin/yaml-lint"
],
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v5.3.6"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-07-29T06:20:01+00:00"
}
],
"packages-dev": [],
@ -1856,7 +2608,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.3.0",
"php": ">=8.0",
"ext-curl": "*",
"ext-openssl": "*",
"ext-sockets": "*",

27
conf/bili.yaml Normal file
View File

@ -0,0 +1,27 @@
bili_version: 0.0.1
# Android
bili_a:
package: "tv.danmaku.bili"
version: "6.38.0"
build: "6380500"
channel: "bili"
device: "phone"
mobi_app: "android"
platform: "android"
s_locale: "zh-Hans_CN"
c_locale: "zh-Hans_CH"
app_key: "MWQ4YjZlN2Q0NTIzMzQzNg=="
secret_key: "NTYwYzUyY2NkMjg4ZmVkMDQ1ODU5ZWQxOGJmZmQ5NzM"
app_key_n: "YmNhN2U4NGMyZDk0N2FjNg=="
secret_key_n: "NjA2OThiYTJmNjhlMDFjZTQ0NzM4OTIwYTBmZmU3Njg="
# IOS
bili_i:
app_key: "MjdlYjUzZmM5MDU4ZjhjMw=="
secret_key: "YzJlZDUzYTc0ZWVlZmUzY2Y5OWZiZDAxZDhjOWMzNzU="
# Tv
bili_t:
app_key: "NDQwOWUyY2U4ZmZkMTJiOA=="
secret_key: "NTliNDNlMDRhZDY5NjVmMzQzMTkwNjJiNDc4ZjgzZGQ="

14
conf/device.yaml Normal file
View File

@ -0,0 +1,14 @@
device_version: 0.0.1
device:
os: "android"
os_ver: "7.1.2"
model: "MuMu"
network: "2" # 1 流量 2 WIFI
other_headers:
ua: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4450.0 Safari/537.36"
pc_headers:
ua: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.30 Safari/537.36 Edg/90.0.818.8"
app_headers:
ua: "Mozilla/5.0 BiliDroid/${bili_a.version} (bbcallen@gmail.com) os/${device.os} model/${device.model} mobi_app/${bili_a.mobi_app} build/${bili_a.build} channel/${bili_a.channel} innerVer/${bili_a.build} osVer/${device.os_ver} network/${device.network}"

View File

@ -27,6 +27,129 @@
},
"Anchor": {
"default": [
"保温服卡",
"上舰",
"上船",
"初始号",
"大航海",
"封面照",
"手机壁纸",
"舰长",
"宝可梦",
"游戏位",
"未名之花",
"美照",
"游戏好友位",
"游戏道具",
"抽号",
"光谱",
"带飞",
"皮肤",
"上电视",
"星际战甲",
"皂片",
"自画像",
"好友",
"西瓜",
"点券",
"明信片",
"正片",
"水友",
"原神",
"看号",
"双排",
"排位",
"古剑奇谭",
"通宝",
"口令码",
"刷箱子",
"第五人格",
"1.11元",
"1.01元",
"文件夹",
"cdk",
"伊格尼斯亡魂",
"1.2元",
"1元",
"1.1元",
"刀币",
"主播自画像",
"SG5531",
"武器箱",
"极限模式",
"伊洛纳密令",
"星耀王者",
"上车",
"优惠券",
"船长",
"王者",
"开船",
"点播",
"1.88元",
"cos",
"照片",
"照骗",
"正片",
"jk照",
"DNF",
"点券",
"1.68元",
"旗开得胜",
"上电视",
"返现",
"1000金瓜子",
"1.66元",
"1RMB",
"1.5元",
"立牌",
"30内兑换一次",
"私照",
"哼歌",
"船员",
"台历",
"靓照",
"晶核",
"壁纸",
"取关三次作废",
"CDK",
"无脸照",
"游戏礼包",
"公测",
"1.23元",
"头像",
"1块钱",
"完美偶像",
"代金卷",
"海报",
"闪蛋",
"月历",
"风中万花",
"表情包",
"体验票",
"深红之网",
"生活照",
"1.33元",
"提督",
"八折券",
"1.2块",
"1.11元",
"打游戏",
"给主播",
"优惠卷",
"艺术鉴赏虚拟门票",
"金豆",
"点歌",
"1.66元",
"1.22元",
"1.23元",
"身材照",
".照.片",
"取关二次作废",
"取关两次作废",
"项目卡",
"账号规划",
"签名照",
"车车",
"拉黑",
"黑名单",
"脸皮厚",

View File

@ -1,11 +1,11 @@
{
"code": 0,
"project":"BiliHelper-personal",
"project": "BiliHelper-personal",
"branch": "master",
"source": "https://github.com/lkeme/BiliHelper-personal",
"raw_url": "https://cdn.jsdelivr.net/gh/lkeme/BiliHelper-personal@master/data/latest_version.json",
"purge_url": "https://purge.jsdelivr.net/gh/lkeme/BiliHelper-personal@master/data/latest_version.json",
"version": "0.9.9.210807",
"version": "1.0.0.210822",
"des": "程序有更新,请及时线上查看更新哦~",
"time": "2021年8月7日11:40:35"
"time": "2021年8月22日11:40:35"
}

View File

@ -14,4 +14,4 @@ require 'vendor/autoload.php';
$app = new BiliHelper\Core\App(__DIR__);
$app->load($argv)
->inspect()
->start();
->start();

3
log/.gitkeep Normal file
View File

@ -0,0 +1,3 @@
# Ignore everything in this directory
*
# Except this file !.gitkeep

View File

@ -10,13 +10,16 @@
namespace BiliHelper\Core;
use BiliHelper\Plugin\Live;
use Throwable;
use Amp\Loop;
use BiliHelper\Script\BaseTask;
use function Amp\asyncCall;
class App
{
private $script_mode = false;
private $loop_mode = true;
private int $mode = 0;
/**
* App constructor.
@ -50,23 +53,30 @@ class App
{
$args = (new BCommand($argv))->run();
$filename = $args->args()[0] ?? 'user.ini';
$this->script_mode = $args->script;
Config::load($filename);
// 加载配置
Config::getInstance()->load($filename);
// 加载设备
Device::getInstance()->load($filename);
// 引导参数
$this->selectMode($args);
$this->restoreMode($args);
return $this;
}
/**
* @use 新任务
* @param string $taskName
* @param string $dir
*/
public function newTask(string $taskName, string $dir)
private function newTask(string $taskName, string $dir)
{
asyncCall(function () use ($taskName, $dir) {
while (true) {
try {
call_user_func(array("BiliHelper\\$dir\\" . $taskName, 'run'), []);
} catch (\Throwable $e) {
} catch (Throwable $e) {
// TODO 多次错误删除tasks_***.json文件
$error_msg = "MSG: {$e->getMessage()} CODE: {$e->getCode()} FILE: {$e->getFile()} LINE: {$e->getLine()}";
Log::error($error_msg);
@ -90,7 +100,7 @@ class App
'DelDynamic' => '批量清理动态(未完成)'
];
$choice = \BiliHelper\Script\BaseTask::choice($scripts, 'UnFollow');
$choice = BaseTask::choice($scripts, 'UnFollow');
$this->newTask($choice, 'Script');
}
@ -141,19 +151,51 @@ class App
Loop::run();
}
/**
* @use 选择模式
* @param object $args
*/
private function selectMode(object $args)
{
// 可能会有其他模式出现 暂定
// 0 默认值 默认模式1 脚本模式 ...
if ($args->script) {
$this->mode = 1;
}
}
/**
* @use 复位模式
* @param object $args
*/
private function restoreMode(object $args)
{
// 复位 后期添加其他复位
if ($args->restore) {
Task::getInstance()->restore();
}
}
/**
* @use 核心运行
*/
public function start()
{
// Todo 模式名称需要优化
if ($this->script_mode) {
Log::info('执行Script模式');
$this->script_m();
} else {
Log::info('执行Loop模式');
$this->loop_m();
switch ($this->mode) {
case 0:
// 默认
Log::info('执行Loop模式');
$this->loop_m();
break;
case 1:
// 脚本
Log::info('执行Script模式');
$this->script_m();
break;
default:
Log::error("请检查,没有选定的执行模式");
exit();
}
}
}

View File

@ -11,11 +11,12 @@
namespace BiliHelper\Core;
use Ahc\Cli\Input\Command;
use Exception;
class BCommand
{
private $argv;
private array $argv;
/**
* Command constructor.
@ -30,10 +31,12 @@ class BCommand
{
$cli = new Command('BHP-S', 'BHP命令行工具.');
$cli->version('0.0.1-dev')
->option('-s --script', '执行的Script模式.',null,false);
->option('-s --script', '执行的Script模式.', null, false)
->option('-r --restore', '任务排程复位(暂定).', null, false);
try {
$args = $cli->parse($this->argv);
} catch (\Exception $e) {
} catch (Exception $e) {
Log::error($e->getMessage());
die('解析命令行参数错误');
}
return $args;

119
src/core/Cache.php Normal file
View File

@ -0,0 +1,119 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
* Source: https://github.com/fzaninotto/Faker/
*/
namespace BiliHelper\Core;
use BiliHelper\Util\Singleton;
use Flintstone\Flintstone;
use Flintstone\Formatter\JsonFormatter;
class Cache
{
use Singleton;
private array $caches;
private Flintstone $cache;
// 文档
// https://www.xeweb.net/flintstone/documentation/
/**
* @use 加载一个缓存
* @param string $classname
* @return \BiliHelper\Core\Cache
*/
private function load(string $classname): static
{
if (!isset($this->caches[$classname])) {
// 如果不存在缓存 初始化 "BHP_username_APP.dat"
$this->caches[$classname] = new Flintstone(
$this->removeSpecStr('BHP_' . getConf('username', 'login.account') . '_' . $classname),
[
'dir' => APP_CACHE_PATH,
'gzip' => true,
'formatter' => new JsonFormatter()
]
);
}
$this->cache = $this->caches[$classname];
return $this;
// self::$instance->set('bob', ['email' => 'bob@site.com', 'password' => '123456']);
}
/**
* @use 获取调用链类
* @return mixed
*/
private function backtraceClass(): mixed
{
// TODO 耦合度过高 需要解耦
$backtraces = debug_backtrace();
array_shift($backtraces);
return pathinfo(basename($backtraces[2]['file']))['filename'];
}
/**
* @use 获取调用类
* @param string $classname
* @return $this
*/
private function getClassObj(string $classname): static
{
if ($classname == '') {
$classname = $this->backtraceClass();
}
return $this->load($classname);
}
/**
* @use 获取值
* @param string $key
* @param string $extra_name
* @return mixed
*/
public function _get(string $key, string $extra_name = ''): mixed
{
// Get a key
// $user = $users->get('bob');
// echo 'Bob, your email is ' . $user['email'];
return $this->getClassObj($extra_name)->cache->get($key);
}
/**
* @use 写入值
* @param string $key
* @param $data
* @param string $extra_name
*/
public function _set(string $key, $data, string $extra_name = '')
{
// Set a key
// $users->set('bob', ['email' => 'bob@site.com', 'password' => '123456']);
$this->getClassObj($extra_name)->cache->set($key, $data);
}
/**
* @use 去除特殊符号
* @param string $data
* @return string
*/
private function removeSpecStr(string $data): string
{
$specs = str_split(".,:;'*?~`!@#$%^&+=)(<>{}]|\/、");
foreach ($specs as $spec) {
$data = str_replace($spec, '', $data);
}
return $data;
}
}

View File

@ -10,96 +10,71 @@
namespace BiliHelper\Core;
use BiliHelper\Util\Singleton;
use Jelix\IniFile\IniModifier;
class Config
{
private static $app_config;
private static $load_file;
private static $last_time;
private static $config_path;
private static $instance;
use Singleton;
private string|array $load_file;
private int|false $last_time;
private IniModifier $app_config;
private string $config_path;
private static function getInstance(): Config
{
if (is_null(self::$instance)) {
self::$instance = new static;
}
return self::$instance;
}
/**
* @use 加载配置
* @param string $load_file
*/
public static function load(string $load_file)
public function load(string $load_file)
{
$config_path = str_replace("\\", "/", APP_CONF_PATH . $load_file);
if (!is_file($config_path)) {
die("配置文件 {$load_file} 加载错误,请参照文档添加配置文件!");
die("配置文件 $load_file 加载错误,请参照文档添加配置文件!");
}
// 给静态参数赋值
self::$load_file = $load_file;
self::$config_path = $config_path;
$this->load_file = $load_file;
$this->config_path = $config_path;
// $config_path = dirname($config_path).DIRECTORY_SEPARATOR.$load_file;
self::$app_config = new IniModifier(self::$config_path);
self::$last_time = fileatime(self::$config_path);
$this->app_config = new IniModifier($this->config_path);
$this->last_time = fileatime($this->config_path);
}
public static function _set($name, $value, $section = 0, $key = null)
/**
* @use 写入值
* @param $name
* @param $value
* @param int|string $section
* @param null $key
* @throws \Jelix\IniFile\IniException
*/
public function _set($name, $value, int|string $section = 0, $key = null)
{
$_instance = self::getInstance();
$_instance::$app_config->setValue($name, $value, $section, $key);
$_instance::$app_config->save();
$this->app_config->setValue($name, $value, $section, $key);
$this->app_config->save();
// 保存修改时间
$_instance::$last_time = fileatime($_instance::$config_path);
$this->last_time = fileatime($this->config_path);
}
public static function _get($name, $section = 0, $key = null)
/**
* @use 获取值
* @param $name
* @param int|string $section
* @param null $key
* @return mixed
*/
public function _get($name, int|string $section = 0, $key = null): mixed
{
$_instance = self::getInstance();
// 判断是否被修改 重新加载文件
// echo $_instance::$last_time.PHP_EOL;
// echo fileatime($_instance::$config_path);
if (fileatime($_instance::$config_path) != $_instance::$last_time) {
$_instance::load($_instance::$load_file);
// echo $this->last_time.PHP_EOL;
// echo fileatime($this->config_path);
if (fileatime($this->config_path) != $this->last_time) {
$this->load($this->load_file);
}
return $_instance::$app_config->getValue($name, $section, $key);
return $this->app_config->getValue($name, $section, $key);
}
}
public static function _put()
{
$_instance = self::getInstance();
}
public static function _del()
{
$_instance = self::getInstance();
}
/**
* 不允许从外部调用以防止创建多个实例
* 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
*/
private function __construct()
{
}
/**
* 防止实例被克隆(这会创建实例的副本)
*/
private function __clone()
{
}
/**
* 防止反序列化(这将创建它的副本)
*/
public function __wakeup()
{
}
}

View File

@ -10,15 +10,19 @@
namespace BiliHelper\Core;
use Exception;
use GuzzleHttp\Pool;
use GuzzleHttp\Client;
use BiliHelper\Tool\Generator;
use GuzzleHttp\Exception\RequestException;
class Curl
{
private static $client;
private static $async_opt;
private static $results = [];
private static $result = [];
private static $buvid = '';
private static Client $client;
private static array $async_opt;
private static array $results = [];
private static array $result = [];
private static string $buvid = '';
/**
* @use POST请求
@ -26,15 +30,15 @@ class Curl
* @param $url
* @param array $params
* @param array $headers
* @param int $timeout
* @param float $timeout
* @return mixed
*/
public static function post($os, $url, $params = [], $headers = [], $timeout = 30)
public static function post($os, $url, array $params = [], array $headers = [], float $timeout = 30.0): mixed
{
Log::debug("POST: {$url}");
Log::debug("POST: $url");
$headers = self::getHeaders($os, $headers);
$payload['form_params'] = count($params) ? $params : [];
$options = self::getClientOpt($payload, $headers);
$options = self::getClientOpt($payload, $headers, $timeout);
$request = self::clientHandle($url, 'post', $options);
$body = $request->getBody();
Log::debug($body);
@ -47,15 +51,15 @@ class Curl
* @param $url
* @param array $params
* @param array $headers
* @param int $timeout
* @param float $timeout
* @return mixed
*/
public static function get($os, $url, $params = [], $headers = [], $timeout = 30)
public static function get($os, $url, array $params = [], array $headers = [], float $timeout = 30.0): mixed
{
Log::debug("GET: {$url}");
Log::debug("GET: $url");
$headers = self::getHeaders($os, $headers);
$payload['query'] = count($params) ? $params : [];
$options = self::getClientOpt($payload, $headers);
$options = self::getClientOpt($payload, $headers, $timeout);
$request = self::clientHandle($url, 'get', $options);
$body = $request->getBody();
Log::debug($body);
@ -68,15 +72,15 @@ class Curl
* @param $url
* @param array $params
* @param array $headers
* @param int $timeout
* @param float $timeout
* @return mixed
*/
public static function put($os, $url, $params = [], $headers = [], $timeout = 30)
public static function put($os, $url, array $params = [], array $headers = [], float $timeout = 30.0): mixed
{
Log::debug("PUT: {$url}");
Log::debug("PUT: $url");
$headers = self::getHeaders($os, $headers);
$payload['json'] = count($params) ? $params : [];
$options = self::getClientOpt($payload, $headers);
$options = self::getClientOpt($payload, $headers, $timeout);
$request = self::clientHandle($url, 'post', $options);
$body = $request->getBody();
Log::debug($body);
@ -89,10 +93,10 @@ class Curl
* @param $url
* @param array $tasks
* @param array $headers
* @param int $timeout
* @param float $timeout
* @return array
*/
public static function async($os, $url, $tasks = [], $headers = [], $timeout = 30): array
public static function async($os, $url, array $tasks = [], array $headers = [], float $timeout = 30.0): array
{
self::$async_opt = [
'tasks' => $tasks,
@ -100,18 +104,18 @@ class Curl
'count' => count($tasks),
'concurrency' => count($tasks) < 10 ? count($tasks) : 10
];
Log::debug("ASYNC: {$url}");
Log::debug("ASYNC: $url");
$headers = self::getHeaders($os, $headers);
$requests = function ($total) use ($url, $headers, $tasks) {
$requests = function ($total) use ($url, $headers, $tasks, $timeout) {
foreach ($tasks as $task) {
yield function () use ($url, $headers, $task) {
yield function () use ($url, $headers, $task, $timeout) {
$payload['form_params'] = $task['payload'];
$options = self::getClientOpt($payload, $headers);
$options = self::getClientOpt($payload, $headers, $timeout);
return self::clientHandle($url, 'postAsync', $options);
};
}
};
$pool = new \GuzzleHttp\Pool(self::$client, $requests(self::$async_opt['count']), [
$pool = new Pool(self::$client, $requests(self::$async_opt['count']), [
'concurrency' => self::$async_opt['concurrency'],
'fulfilled' => function ($response, $index) {
$res = $response->getBody();
@ -123,7 +127,7 @@ class Curl
self::countedAndCheckEnded();
},
'rejected' => function ($reason, $index) {
Log::error("多线程第{$index}个请求失败, ERROR: {$reason}");
Log::error("多线程第 $index 个请求失败, ERROR: $reason");
self::countedAndCheckEnded();
},
]);
@ -142,9 +146,9 @@ class Curl
* @param int $timeout
* @return false|string|null
*/
public static function request($method, $url, $payload = [], $headers = [], $timeout = 10)
public static function request($method, $url, array $payload = [], array $headers = [], int $timeout = 10): bool|string|null
{
Log::debug("REQUEST: {$url}");
Log::debug("REQUEST: $url");
$options = array(
'http' => array(
'method' => strtoupper($method),
@ -178,23 +182,23 @@ class Curl
* @param array $options
* @return mixed
*/
private static function clientHandle(string $url, string $method, array $options)
private static function clientHandle(string $url, string $method, array $options): mixed
{
$max_retry = range(1, 40);
foreach ($max_retry as $retry) {
try {
$response = call_user_func_array([self::$client, $method], [$url, $options]);
if (is_null($response) or empty($response)) throw new \Exception("Value IsEmpty");
if (is_null($response) or empty($response)) throw new Exception("Value IsEmpty");
return $response;
} catch (\GuzzleHttp\Exception\RequestException $e) {
} catch (RequestException $e) {
// var_dump($e->getRequest());
if ($e->hasResponse()) var_dump($e->getResponse());
} catch (\Exception $e) {
} catch (Exception $e) {
// $e->getHandlerContext()
// var_dump($e);
}
Log::warning("Target -> URL: {$url} METHOD: {$method}");
Log::warning("CURl -> RETRY: {$retry} ERROR: {$e->getMessage()} ERRNO: {$e->getCode()} STATUS: Waiting for recovery!");
Log::warning("Target -> URL: $url METHOD: $method");
Log::warning("CURl -> RETRY: $retry ERROR: {$e->getMessage()} ERRNO: {$e->getCode()} STATUS: Waiting for recovery!");
sleep(15);
}
exit('网络异常,超出最大尝试次数,退出程序~');
@ -209,7 +213,7 @@ class Curl
*/
private static function getClientOpt(array $add_options, array $headers = [], float $timeout = 30.0): array
{
self::$client = new \GuzzleHttp\Client();
self::$client = new Client();
$default_options = [
'headers' => $headers,
'timeout' => $timeout,
@ -231,8 +235,16 @@ class Curl
private static function getHeaders(string $os = 'app', array $headers = []): array
{
if (!self::$buvid) {
self::$buvid = Generator::buvid();
// 缓存开始 如果存在就赋值 否则默认值
if ($temp = getCache('buvid')) {
self::$buvid = $temp;
} else {
self::$buvid = Generator::buvid();
}
// 缓存结束 需要的数据的放进缓存
setCache('buvid', self::$buvid);
}
$app_headers = [
'env' => 'prod',
'APP-KEY' => 'android',
@ -241,21 +253,21 @@ class Curl
'Accept-Encoding' => 'gzip',
'Accept-Language' => 'zh-cn',
'Connection' => 'keep-alive',
'User-Agent' => getDevice('device.app_headers.ua'),
// 'Content-Type' => 'application/x-www-form-urlencoded',
// 'User-Agent' => 'Mozilla/5.0 BiliDroid/5.51.1 (bbcallen@gmail.com)',
'User-Agent' => 'Mozilla/5.0 BiliDroid/6.36.0 (bbcallen@gmail.com) os/android model/MuMu mobi_app/android build/6360400 channel/bili innerVer/6360400 osVer/7.1.2 network/2',
// 'Referer' => 'https://live.bilibili.com/',
];
$pc_headers = [
'Accept' => "application/json, text/plain, */*",
'Accept-Encoding' => 'gzip, deflate',
'Accept-Language' => "zh-CN,zh;q=0.9",
'User-Agent' => getDevice('device.pc_headers.ua'),
// 'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.30 Safari/537.36 Edg/90.0.818.8',
// 'Referer' => 'https://live.bilibili.com/',
];
$other_headers = [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4450.0 Safari/537.36',
'User-Agent' => getDevice('device.other_headers.ua')
];
$default_headers = ${$os . "_headers"} ?? $other_headers;
if (in_array($os, ['app', 'pc']) && getCookie() != "") {
@ -279,14 +291,13 @@ class Curl
/**
* @use 关联数组转字符串
* @param array $array
* @param string $separator
* @return string
*/
private static function arr2str(array $array, string $separator = "\r\n"): string
private static function arr2str(array $array): string
{
$tmp = '';
foreach ($array as $key => $value) {
$tmp .= "{$key}:{$value}{$separator}";
$tmp .= "$key:$value\r\n";
}
return $tmp;
}
@ -297,16 +308,16 @@ class Curl
* @param $url
* @param array $params
* @param array $headers
* @param int $timeout
* @param float $timeout
* @return mixed
*/
public static function headers($os, $url, $params = [], $headers = [], $timeout = 30)
public static function headers($os, $url, array $params = [], array $headers = [], float $timeout = 30.0): mixed
{
Log::debug('HEADERS: ' . $url);
$headers = self::getHeaders($os, $headers);
$payload['query'] = count($params) ? $params : [];
$payload['allow_redirects'] = false;
$options = self::getClientOpt($payload, $headers);
$options = self::getClientOpt($payload, $headers, $timeout);
$request = self::clientHandle($url, 'get', $options);
Log::debug("获取Headers");
return $request->getHeaders();

67
src/core/Device.php Normal file
View File

@ -0,0 +1,67 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Core;
use BiliHelper\Util\Singleton;
use Consolidation\Config\Config;
use Consolidation\Config\Loader\YamlConfigLoader;
use Consolidation\Config\Loader\ConfigProcessor;
class Device
{
use Singleton;
private Config $device;
private string $bili_file = 'bili.yaml';
private string $device_file = 'device.yaml';
/**
* 加载配置
*/
public function load(string $load_file)
{
// 提前处理 后缀
$custom_file = str_replace(strrchr($load_file, "."), "", $load_file) . '_';
// 自定义客户端
if (is_file(APP_CONF_PATH . $custom_file . $this->bili_file)) {
$this->bili_file = APP_CONF_PATH . $custom_file . $this->bili_file;
Log::info('使用自定义Bili.yaml');
}
// 自定义设备
if (is_file(APP_CONF_PATH . $custom_file . $this->device_file)) {
$this->device_file = APP_CONF_PATH . $custom_file . $this->device_file;
Log::info('使用自定义Device.yaml');
}
// 加载数据
$this->device = new Config();
$loader = new YamlConfigLoader();
$processor = new ConfigProcessor();
$files = [$this->bili_file, $this->device_file];
// 循环加载
foreach ($files as $file) {
$processor->extend($loader->load(APP_CONF_PATH . $file));
}
$this->device->import($processor->export());
}
/**
* @use 获取值
* @param $key
* @param null $defaultFallback
* @return mixed
*/
public function _get($key, $defaultFallback = null): mixed
{
return $this->device->get($key, $defaultFallback);
}
}

View File

@ -14,12 +14,12 @@ use Noodlehaus\Config;
class Env
{
private $app_name;
private $app_version;
private $app_branch;
private $app_source;
private string $app_name;
private string $app_version;
private string $app_branch;
private string $app_source;
private $repository = APP_DATA_PATH . 'latest_version.json';
private string $repository = APP_DATA_PATH . 'latest_version.json';
/**
@ -45,9 +45,9 @@ class Env
$default_extensions = ['curl', 'openssl', 'sockets', 'json', 'zlib', 'mbstring'];
foreach ($default_extensions as $extension) {
if (!extension_loaded($extension)) {
Log::error("检查到项目依赖 {$extension} 扩展未加载。");
Log::error("请在 php.ini中启用 {$extension} 扩展后重试。");
Log::error("程序常见问题请移步 {$this->app_source} 文档部分查看。");
Log::error("检查到项目依赖 $extension 扩展未加载。");
Log::error("请在 php.ini中启用 $extension 扩展后重试。");
Log::error("程序常见问题请移步 $this->app_source 文档部分查看。");
exit();
}
}
@ -58,18 +58,18 @@ class Env
*/
public function inspect_configure(): Env
{
Log::info("欢迎使用 项目: {$this->app_name}@{$this->app_branch} 版本: {$this->app_version}");
Log::info("使用说明请移步 {$this->app_source} 查看");
Log::info("欢迎使用 项目: $this->app_name@$this->app_branch 版本: $this->app_version");
Log::info("使用说明请移步 $this->app_source 查看");
if (PHP_SAPI != 'cli') {
die("Please run this script from command line .");
}
if (version_compare(PHP_VERSION, '7.3.0', '<')) {
die("Please upgrade PHP version > 7.3.0 .");
}
// if (version_compare(PHP_VERSION, '8.0.0', '>')) {
// die("Please upgrade PHP version < 8.0.0 .");
// if (version_compare(PHP_VERSION, '7.4.0', '<')) {
// die("Please upgrade PHP version > 7.4.0 .");
// }
if (version_compare(PHP_VERSION, '8.0.0', '<')) {
die("Please upgrade PHP version < 8.0.0 .");
}
return $this;
}

View File

@ -8,46 +8,33 @@
* Updated: 2021 ~ 2022
*/
use BiliHelper\Core\Cache;
use BiliHelper\Core\Config;
use BiliHelper\Core\Device;
/**
* @use 读取
* @use 配置读取
* @param $name
* @param int $section
* @param int|string $section
* @param null $key
* @return mixed
*/
function getConf($name, $section = 0, $key = null)
function getConf($name, int|string $section = 0, $key = null): mixed
{
return Config::_get($name, $section, $key);
return Config::getInstance()->_get($name, $section, $key);
}
/**
* @use 写入
* @use 配置写入
* @param $name
* @param $value
* @param int $section
* @param int|string $section
* @param null $key
* @throws \Jelix\IniFile\IniException
*/
function setConf($name, $value, $section = 0, $key = null)
function setConf($name, $value, int|string $section = 0, $key = null)
{
Config::_set($name, $value, $section, $key);
}
/**
* @use 更新
*/
function putConf()
{
}
/**
* @use 删除
*/
function delConf()
{
Config::getInstance()->_set($name, $value, $section, $key);
}
/**
@ -105,13 +92,35 @@ function getCsrf(): string
return getConf('csrf', 'login.auth');
}
/**
* @use 获取设备信息
* @param $key
* @param null $defaultFallback
* @return mixed
*/
function getDevice($key, $defaultFallback = null): mixed
{
return Device::getInstance()->_get($key, $defaultFallback);
}
/**
* @use HttpClient
* @param string $url
* @return \HttpClient
* @use 缓存读取
* @param string $key
* @param string $extra_name
* @return mixed
*/
function newHttp(string $url): HttpClient
function getCache(string $key, string $extra_name = ''): mixed
{
return new HttpClient($url);
}
return Cache::getInstance()->_get($key, $extra_name);
}
/**
* @use 缓存写入
* @param string $key
* @param $data
* @param string $extra_name
*/
function setCache(string $key, $data, string $extra_name = '')
{
Cache::getInstance()->_set($key, $data, $extra_name);
}

View File

@ -13,147 +13,157 @@ namespace BiliHelper\Core;
class HttpClient
{
private $ch;
private $ret;
private $form;
private $headers;
private $url;
private $query;
public function __construct(string $url)
{
$this->ch = curl_init();
$this->url = $url;
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false); //忽略 HTTPS 证书错误
$this->setUA("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36");
}
function __destruct()
{
//防止内存泄露
curl_close($this->ch);
}
/**
* @use 设置UA
* @param string $ua
* @return $this
*/
public function setUA(string $ua): HttpClient
{
curl_setopt($this->ch, CURLOPT_USERAGENT, $ua); //设置 UA
return $this;
}
/**
* @use 添加Header
* @param string $header
* @return $this
*/
public function addHeader(string $header): HttpClient
{
array_push($this->headers, $header);
return $this;
}
/**
* @use 添加Headers
* @param array $headers
* @return $this
*/
public function addHeaders(array $headers): HttpClient
{
foreach ($headers as $key => $value) {
array_push($this->headers, "{$key}: {$value}");
}
return $this;
}
/**
* @use 设置Cookie
* @param string $cookie
* @return $this
*/
public function setCookie(string $cookie): HttpClient
{
curl_setopt($this->ch, CURLOPT_COOKIE, $cookie);
return $this;
}
/**
* @use 设置 url 参数
*/
public function buildQuery(array $query): HttpClient
{
$this->query = http_build_query($query);
return $this;
}
/**
* @use 自动将 json 文本解码
*/
public function asJSON(): object
{
return json_decode($this->ret);
}
/**
* @use 获取返回结果
*/
public function asString(): string
{
return $this->ret;
}
/**
* @use 构造POST表单
* @param array $form
* @return $this
*/
public function buildPostForm(array $form): HttpClient
{
$this->form = http_build_query($form);
return $this;
}
/**
* @use 发送 Get 请求
*/
public function get(): HttpClient
{
curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中
curl_setopt($this->ch, CURLOPT_HEADER, $this->headers);
$this->ret = curl_exec($this->ch);
return $this;
}
/**
* @use 发送 POST 请求
* @param string|null $data POST 的数据
* @return \HttpClient
*/
public function post(string $data = null): HttpClient
{
curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中
curl_setopt($this->ch, CURLOPT_POST, true); // 发送 POST 请求
curl_setopt($this->ch, CURLOPT_HEADER, $this->headers);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
$this->ret = curl_exec($this->ch);
return $this;
}
/**
* @use POST表单
* @param array $form
* @return $this
*/
public function postForm(array $form): HttpClient
{
return $this->post(http_build_query($form));
}
// private $ch;
// private $ret;
// private $form;
// private $headers;
// private $url;
// private $query;
//
// public function __construct(string $url)
// {
// $this->ch = curl_init();
// $this->url = $url;
// curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false); //忽略 HTTPS 证书错误
// $this->setUA("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36");
// }
//
// function __destruct()
// {
// //防止内存泄露
// curl_close($this->ch);
// }
//
// /**
// * @use 设置UA
// * @param string $ua
// * @return $this
// */
// public function setUA(string $ua): HttpClient
// {
// curl_setopt($this->ch, CURLOPT_USERAGENT, $ua); //设置 UA
// return $this;
// }
//
// /**
// * @use 添加Header
// * @param string $header
// * @return $this
// */
// public function addHeader(string $header): HttpClient
// {
// array_push($this->headers, $header);
// return $this;
// }
//
// /**
// * @use 添加Headers
// * @param array $headers
// * @return $this
// */
// public function addHeaders(array $headers): HttpClient
// {
// foreach ($headers as $key => $value) {
// array_push($this->headers, "{$key}: {$value}");
// }
// return $this;
// }
//
// /**
// * @use 设置Cookie
// * @param string $cookie
// * @return $this
// */
// public function setCookie(string $cookie): HttpClient
// {
// curl_setopt($this->ch, CURLOPT_COOKIE, $cookie);
// return $this;
// }
//
// /**
// * @use 设置 url 参数
// */
// public function buildQuery(array $query): HttpClient
// {
// $this->query = http_build_query($query);
// return $this;
// }
//
// /**
// * @use 自动将 json 文本解码
// */
// public function asJSON(): object
// {
// return json_decode($this->ret);
// }
//
// /**
// * @use 获取返回结果
// */
// public function asString(): string
// {
// return $this->ret;
// }
//
// /**
// * @use 构造POST表单
// * @param array $form
// * @return $this
// */
// public function buildPostForm(array $form): HttpClient
// {
// $this->form = http_build_query($form);
//
// return $this;
// }
//
// /**
// * @use 发送 Get 请求
// */
// public function get(): HttpClient
// {
// curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query);
// curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中
// curl_setopt($this->ch, CURLOPT_HEADER, $this->headers);
// $this->ret = curl_exec($this->ch);
// return $this;
// }
//
// /**
// * @use 发送 POST 请求
// * @param string|null $data 要 POST 的数据
// * @return \HttpClient
// */
// public function post(string $data = null): HttpClient
// {
// curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query);
// curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中
// curl_setopt($this->ch, CURLOPT_POST, true); // 发送 POST 请求
// curl_setopt($this->ch, CURLOPT_HEADER, $this->headers);
// curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
// $this->ret = curl_exec($this->ch);
// return $this;
// }
//
//
// /**
// * @use POST表单
// * @param array $form
// * @return $this
// */
// public function postForm(array $form): HttpClient
// {
// return $this->post(http_build_query($form));
// }
}
///**
// * @use HttpClient
// * @param string $url
// * @return \BiliHelper\Core\HttpClient
// */
//function newHttp(string $url): HttpClient
//{
// return new HttpClient($url);
//}

View File

@ -49,7 +49,7 @@ class Log
{
if (getConf('multiple', 'print')) {
// return '[' . (getConf('user_identity', 'print') ?? getConf('username', 'login.account')) . ']';
return sprintf("[%s]",getConf('user_identity', 'print') ?? getConf('username', 'login.account'));
return sprintf("[%s]", getConf('user_identity', 'print') ?? getConf('username', 'login.account'));
}
return '';
}

View File

@ -10,37 +10,26 @@
namespace BiliHelper\Core;
use BiliHelper\Tool\File;
use BiliHelper\Util\Singleton;
class Task
{
private static $init = true;
private static $repository = null;
private static $instance;
use Singleton;
/**
* @use 单例
* @return \BiliHelper\Core\Task
*/
public static function getInstance(): Task
{
if (is_null(self::$instance)) {
self::$instance = new static;
}
return self::$instance;
}
private string $repository = '';
/**
* @use 初始化
*/
private static function init()
protected function init()
{
if (self::$init) {
// 赋值仓库地址
if (is_null(self::$repository)) {
self::$repository = APP_TASK_PATH . 'tasks_' . getConf('username', 'login.account') . '.json';
}
// 赋值仓库地址
if ($this->repository == '') {
$this->repository = APP_TASK_PATH . 'tasks_' . getConf('username', 'login.account') . '.json';
// 仓库不存在自动创建
if (!file_exists(self::$repository)) {
$fh = fopen(self::$repository, "w");
if (!file_exists($this->repository)) {
$fh = fopen($this->repository, "w");
fwrite($fh, "{}");
fclose($fh);
Log::info('任务排程文件不存在,初始化所有任务。');
@ -48,18 +37,15 @@ class Task
Log::info('任务排程文件存在,继续执行所有任务。');
}
}
// 限制初始化
self::$init = false;
}
/**
* @use
* @return array
*/
private static function read(): array
private function read(): array
{
self::init();
$data = file_get_contents(self::$repository);
$data = file_get_contents($this->repository);
return json_decode($data, true);
}
@ -68,10 +54,9 @@ class Task
* @param array $data
* @return bool
*/
private static function write(array $data): bool
private function write(array $data): bool
{
self::init();
return file_put_contents(self::$repository, json_encode($data));
return file_put_contents($this->repository, json_encode($data));
}
/**
@ -80,11 +65,11 @@ class Task
* @param int $lock
* @return bool
*/
public static function _setLock(string $class, int $lock): bool
public function _setLock(string $class, int $lock): bool
{
$data = self::read();
$data = $this->read();
$data[$class] = $lock;
return self::write($data);
return $this->write($data);
}
/**
@ -92,13 +77,24 @@ class Task
* @param string $class
* @return int
*/
public static function _getLock(string $class): int
public function _getLock(string $class): int
{
$data = self::read();
$data = $this->read();
if (array_key_exists($class, $data)) {
return $data[$class];
}
return 0;
}
/**
* @use 复位
*/
public function restore()
{
Log::info('复位任务排程文件。');
File::del($this->repository);
$this->repository = '';
$this->init();
}
}

View File

@ -0,0 +1,19 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
declare(strict_types=1);
namespace BiliHelper\Exceptions;
use Exception;
class SingletonException extends Exception
{
}

View File

@ -0,0 +1,19 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
declare(strict_types=1);
namespace BiliHelper\Exceptions;
use Exception;
class TaskException extends Exception
{
}

View File

@ -20,7 +20,7 @@ class ActivityLottery
use TimeLock;
use AllotTasks;
private static $repository = APP_DATA_PATH . 'activity_infos.json';
private static string $repository = APP_DATA_PATH . 'activity_infos.json';
/**
* @throws \JsonDecodeStream\Exception\TokenizerException
@ -78,7 +78,7 @@ class ActivityLottery
}
// draw_times
$arr = range(1, $act->draw_times);
foreach ($arr as $_) {
foreach ($arr as $ignored) {
self::pushTask('draw', $act);
}
}
@ -153,7 +153,7 @@ class ActivityLottery
Log::notice("剩余抽奖次数 {$de_raw['data']['times']}");
return true;
}
Log::warning("获取抽奖次数失败 {$raw}");
Log::warning("获取抽奖次数失败 $raw");
return false;
}
if ($de_raw['code'] == 0) {
@ -163,7 +163,7 @@ class ActivityLottery
}
return true;
}
Log::warning("获取抽奖次数失败 {$raw}");
Log::warning("获取抽奖次数失败 $raw");
return false;
}
@ -193,7 +193,7 @@ class ActivityLottery
// {"code":75003,"message":"活动已结束","ttl":1}
// {"code":0,"message":"0","ttl":1}
$de_raw = json_decode($raw, true);
Log::notice("增加抽奖机会#{$action_type} {$raw}");
Log::notice("增加抽奖机会#$action_type $raw");
if ($de_raw['code'] == 0) {
return true;
@ -222,11 +222,11 @@ class ActivityLottery
];
$raw = Curl::post('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
Log::notice("开始抽奖#{$num} {$raw}");
Log::notice("开始抽奖#$num $raw");
// {"code":0,"message":"0","ttl":1,"data":[{"id":0,"mid":4133274,"num":1,"gift_id":1152,"gift_name":"硬币x6","gift_type":0,"img_url":"https://i0.hdslb.com/bfs/activity-plat/static/b6e956937ee4aefd1e19c01283145fc0/JQ9Y9-KCm_w96_h102.png","type":5,"ctime":1596255796,"cid":0}]}
// {"code":0,"message":"0","ttl":1,"data":[{"id":0,"mid":4133274,"ip":0,"num":1,"gift_id":0,"gift_name":"未中奖0","gift_type":0,"img_url":"","type":1,"ctime":1616825625,"cid":0,"extra":{}}]}
if ($de_raw['code'] == 0) {
$result = "活动->{$referer} 获得->{$de_raw['data'][0]['gift_name']}";
$result = "活动->$referer 获得->{$de_raw['data'][0]['gift_name']}";
Notice::push('activity_lottery', $result);
return true;
}

View File

@ -20,12 +20,12 @@ class AloneTcpClient
{
use TimeLock;
private static $heart_lock = 0;
private static int $heart_lock = 0;
private static $client = null;
private static $server_addr = null;
private static $server_key = null;
private static $socket_timeout = 0;
private static $max_errors_num = 0; // 最大连续错误5次
private static int $socket_timeout = 0;
private static int $max_errors_num = 0; // 最大连续错误5次
/**
* @use 入口
@ -74,10 +74,10 @@ class AloneTcpClient
* @use 数据解包
* @param $value
* @param string $fmt
* @return array|false
* @return mixed
* @throws \Exception
*/
private static function unPackMsg($value, string $fmt = "N")
private static function unPackMsg($value, string $fmt = "N"):mixed
{
return unpack($fmt, $value)[1];
}
@ -114,9 +114,9 @@ class AloneTcpClient
/**
* @use 读数据
* @param $length
* @return array|bool
* @return mixed
*/
private static function reader($length)
private static function reader($length): mixed
{
$data = false;
try {
@ -216,7 +216,7 @@ class AloneTcpClient
switch ($data_type) {
case 'raffle':
// 抽奖推送
Log::debug("(receive={$body})");
Log::debug("(receive=$body)");
DataTreating::distribute($raw_data['data']);
break;
case 'entered':
@ -229,7 +229,7 @@ class AloneTcpClient
Log::error("推送服务器异常 {$raw_data['data']['msg']}, 程序错误5次后将挂起, 请手动关闭!");
if (self::$max_errors_num == 5) {
// KEY到期推送提醒
Notice::push('key_expired', '');
Notice::push('key_expired');
// 程序挂起 防止systemd无限重启导致触发过多推送提醒
sleep(86400);
exit();
@ -258,7 +258,7 @@ class AloneTcpClient
default:
// 未知信息
var_dump($raw_data);
Log::info("出现未知信息 {$body}");
Log::info("出现未知信息 $body");
// 出现未知信息 处理重连 防止内存益处
self::reConnect();
break;
@ -278,8 +278,7 @@ class AloneTcpClient
}
$filename = $path . getConf('username', 'login.account') . ".log";
$date = date('[Y-m-d H:i:s] ');
$data = "[{$date}]{$message}" . PHP_EOL;
$data = "[$date]$message" . PHP_EOL;
file_put_contents($filename, $data, FILE_APPEND);
return;
}
}

View File

@ -19,18 +19,18 @@ class AnchorRaffle extends BaseRaffle
const ACTIVE_TITLE = '天选之子';
const ACTIVE_SWITCH = 'live_anchor';
protected static $wait_list = [];
protected static $finish_list = [];
protected static $all_list = [];
protected static array $wait_list = [];
protected static array $finish_list = [];
protected static array $all_list = [];
// 过滤类型
private static $filter_type = [];
private static array $filter_type = [];
// 默认关注 特殊关注 等待关注
private static $default_follows = [];
private static $special_follows = [];
public static $wait_un_follows = [];
private static array $default_follows = [];
private static array $special_follows = [];
public static array $wait_un_follows = [];
// 特殊分组 分组ID
private static $group_name = "玄不改非"; // 氪不改命
private static $group_id = null;
private static string $group_name = "玄不改非"; // 氪不改命
private static int|null $group_id = null;
/**
@ -64,9 +64,9 @@ class AnchorRaffle extends BaseRaffle
self::$group_id = $tag_id ?: User::createRelationTag(self::$group_name);
}
// 获取需要关注的
$data = Live::getRoomInfoV1($room_id);
if ($data['code'] == 0 && isset($data['data'])) {
$need_follow_uid = $data['data']['uid'];
$data = Live::getRealRoomID($room_id, true);
if ($data['uid']) {
$need_follow_uid = $data['uid'];
} else {
return;
}
@ -129,7 +129,7 @@ class AnchorRaffle extends BaseRaffle
$custom_words = empty($words = getConf('filter_words', 'live_anchor')) ? [] : explode(',', $words);
$total_words = array_merge($default_words, $custom_words);
foreach ($total_words as $word) {
if (strpos($prize_name, $word) !== false) {
if (str_contains($prize_name, $word)) {
return true;
}
}
@ -221,9 +221,9 @@ class AnchorRaffle extends BaseRaffle
/**
* @use 解析抽奖信息
* @param array $results
* @return void
* @return mixed
*/
protected static function parseLottery(array $results)
protected static function parseLottery(array $results): mixed
{
foreach ($results as $result) {
$data = $result['source'];
@ -240,5 +240,6 @@ class AnchorRaffle extends BaseRaffle
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . "-(" . $data['raffle_name'] . "): {$de_raw['message']}");
}
}
return '';
}
}

View File

@ -18,12 +18,12 @@ class AwardRecord
{
use TimeLock;
private static $raffle_lock = 0;
private static $raffle_list = [];
private static $anchor_lock = 0;
private static $anchor_list = [];
private static $gift_lock = 0;
private static $gift_list = [];
private static int $raffle_lock = 0;
private static array $raffle_list = [];
private static int $anchor_lock = 0;
private static array $anchor_list = [];
private static int $gift_lock = 0;
private static array $gift_list = [];
public static function run()
{
@ -69,7 +69,7 @@ class AwardRecord
// 范围
if ($day <= 2) {
$info = $anchor['award_name'] . 'x' . $anchor['award_num'];
Log::notice("天选时刻于" . $anchor['end_time'] . "获奖: {$info} ,请留意查看...");
Log::notice("天选时刻于" . $anchor['end_time'] . "获奖: $info ,请留意查看...");
Notice::push('anchor', $info);
}
array_push(self::$anchor_list, $anchor['id']);
@ -82,7 +82,7 @@ class AwardRecord
if (in_array($wait_un_follow['anchor_id'], self::$anchor_list)) {
AnchorRaffle::delToGroup($wait_un_follow['uid'], $wait_un_follow['anchor_id'], false);
} else {
AnchorRaffle::delToGroup($wait_un_follow['uid'], $wait_un_follow['anchor_id'], true);
AnchorRaffle::delToGroup($wait_un_follow['uid'], $wait_un_follow['anchor_id']);
}
}
@ -118,7 +118,7 @@ class AwardRecord
// 范围
if ($day <= 2 && empty($raffle['update_time'])) {
$info = $raffle['gift_name'] . 'x' . $raffle['gift_num'];
Log::notice("实物奖励于" . $raffle['create_time'] . "获奖: {$info} ,请留意查看...");
Log::notice("实物奖励于" . $raffle['create_time'] . "获奖: $info ,请留意查看...");
Notice::push('raffle', $info);
}
array_push(self::$raffle_list, $raffle['id']);

View File

@ -13,6 +13,7 @@ namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
use Exception;
class Barrage
{
@ -69,11 +70,12 @@ class Barrage
}
return $data;
}
} catch (\Exception $e) {
} catch (Exception $e) {
return $e->getMessage();
}
}
/**
* @use 活跃弹幕
* @return bool
@ -88,10 +90,10 @@ class Barrage
// {"code":0,"message":"你被禁言啦","msg":"你被禁言啦"}
// Todo 长度限制
if (isset($response['code']) && $response['code'] == 0 && isset($response['data'])) {
Log::notice("在直播间@{$room_id} 发送活跃弹幕成功 CODE -> {$response['code']}");
Log::notice("在直播间@$room_id 发送活跃弹幕成功 CODE -> {$response['code']}");
return true;
} else {
Log::warning("在直播间@{$room_id} 发送活跃弹幕失败 CODE -> {$response['code']} MSG -> {$response['message']} ");
Log::warning("在直播间@$room_id 发送活跃弹幕失败 CODE -> {$response['code']} MSG -> {$response['message']} ");
return false;
}
}

View File

@ -44,7 +44,6 @@ class BpConsumption
// 消费B币充值金瓜子
if (getConf('bp2gold', 'bp_consumption')) {
self::BP2gold($bp_balance);
return;
}
}
}
@ -76,7 +75,7 @@ class BpConsumption
Log::notice('获取钱包成功 B币券余额剩余' . $de_raw['data']['couponBalance']);
return intval($de_raw['data']['couponBalance']);
} else {
Log::warning("获取钱包失败 {$raw}");
Log::warning("获取钱包失败 $raw");
return 0;
}
}

View File

@ -24,8 +24,8 @@ class CapsuleLottery
use AllotTasks;
use XliveHeartBeat;
private static $repository = APP_DATA_PATH . 'capsule_infos.json';
private static $interval = 60;
private static string $repository = APP_DATA_PATH . 'capsule_infos.json';
private static int $interval = 60;
/**
@ -78,7 +78,7 @@ class CapsuleLottery
self::pushTask('watch', $act, true);
// 抽奖次数
$arr = range(1, $act->draw_times);
foreach ($arr as $_) {
foreach ($arr as $ignored) {
self::pushTask('draw', $act);
}
}
@ -155,10 +155,10 @@ class CapsuleLottery
];
$raw = Curl::post('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
Log::notice("开始抽奖#{$num} {$raw}");
Log::notice("开始抽奖#$num $raw");
// {"code":0,"message":"0","ttl":1,"data":{"status":false,"isEntity":false,"info":{"coin":1},"awards":[{"name":"谢谢参与","num":1,"text":"谢谢参与 X 1","web_url":"https://i0.hdslb.com/bfs/live/b0fccfb3bac2daae35d7e514a8f6d31530b9add2.png","mobile_url":"https://i0.hdslb.com/bfs/live/b0fccfb3bac2daae35d7e514a8f6d31530b9add2.png","usage":{"text":"很遗憾您未能中奖","url":""},"type":32,"expire":"当天","gift_type":"7290bc172e5ab9e151eb141749adb9dd","gift_value":""}],"text":["谢谢参与 X 1"],"isExCode":false}}
if ($de_raw['code'] == 0) {
$result = "活动->{$referer} 获得->{$de_raw['data']['text'][0]}";
$result = "活动->$referer 获得->{$de_raw['data']['text'][0]}";
Notice::push('capsule_lottery', $result);
return true;
}
@ -248,7 +248,7 @@ class CapsuleLottery
Log::info("获取剩余抽奖次数成功 {$capsule_info['data']['coin']}");
return $capsule_info['data']['coin'];
}
Log::warning("获取剩余抽奖次数失败 {$capsule_info}");
Log::warning("获取剩余抽奖次数失败 $capsule_info");
return 0;
}

View File

@ -20,9 +20,9 @@ class CheckUpdate
{
use TimeLock;
private static $current_conf;
private static $latest_conf;
private static $repository = APP_DATA_PATH . 'latest_version.json';
private static object $current_conf;
private static object $latest_conf;
private static string $repository = APP_DATA_PATH . 'latest_version.json';
public static function run()
@ -51,7 +51,7 @@ class CheckUpdate
$time = self::$latest_conf->get('time');
$version = self::$latest_conf->get('version');
$des = self::$latest_conf->get('des');
$info = "最新版本-{$version}, {$des}";
$info = "最新版本-$version, $des";
Notice::push('update', $info);
}
}

View File

@ -73,7 +73,7 @@ class Competition
if ($de_raw['code'] == 0) {
Log::notice("破产成功: {$de_raw['message']}");
} else {
Log::warning("破产失败: {$raw}");
Log::warning("破产失败: $raw");
}
}
@ -115,7 +115,7 @@ class Competition
}
$guess['detail_id'] = $detail['detail_id'];
$profit = ceil($guess['count'] * $detail['odds']);
$guess['estimate'] = "竞猜队伍: {$detail['option']} 预计下注: {$guess['count']} 预计赚取: {$profit} 预计亏损: {$guess['count']} (硬币)";
$guess['estimate'] = "竞猜队伍: {$detail['option']} 预计下注: {$guess['count']} 预计赚取: $profit 预计亏损: {$guess['count']} (硬币)";
return $guess;
}

View File

@ -36,9 +36,9 @@ class DailyTask
/**
* @use 检查每日任务
* @return bool|mixed|string
* @return mixed
*/
private static function check()
private static function check(): mixed
{
$url = 'https://api.live.bilibili.com/i/api/taskInfo';
$payload = [];

View File

@ -10,6 +10,8 @@
namespace BiliHelper\Plugin;
use Exception;
class DataTreating
{
// Todo 独立分发 Push||Pull数据
@ -23,7 +25,7 @@ class DataTreating
// room_id raffle_id raffle_title raffle_type
try {
$info = ['rid' => $data['room_id'], 'lid' => $data['raffle_id']];
} catch (\Exception $e) {
} catch (Exception $e) {
return;
}
switch ($data['raffle_type']) {

View File

@ -21,7 +21,7 @@ class Dynamic
// https://api.vc.bilibili.com/topic_svr/v1/topic_svr/fetch_dynamics?topic_name=%E4%BA%92%E5%8A%A8%E6%8A%BD%E5%A5%96&sortby=2
// https://t.bilibili.com/topic/name/%E5%8A%A8%E6%80%81%E6%8A%BD%E5%A5%96/feed
private static $topic_list = [
private static array $topic_list = [
'互动抽奖' => '3230836',
'转发抽奖' => '434405',
'动态抽奖' => '7146512',
@ -37,7 +37,7 @@ class Dynamic
];
private static $article_list = [];
private static array $article_list = [];
/**
* 获取抽奖话题下的帖子
@ -45,7 +45,7 @@ class Dynamic
public static function getAwardTopic(): array
{
foreach (self::$topic_list as $t_name => $t_id) {
Log::info("获取关键字 {$t_name}-{$t_id}");
Log::info("获取关键字 $t_name - $t_id");
$url = 'https://api.vc.bilibili.com/topic_svr/v1/topic_svr/topic_new?topic_id=' . $t_id;
$data = Curl::request('get', $url);
$data = json_decode($data, true);
@ -93,7 +93,7 @@ class Dynamic
// https://api.vc.bilibili.com/topic_svr/v1/topic_svr/topic_history?topic_name=转发抽奖&offset_dynamic_id=454347930068783808
}
$num = count(self::$article_list);
Log::info("获取到 {$num} 条有效动态");
Log::info("获取到 $num 条有效动态");
return self::$article_list;
}
@ -210,7 +210,7 @@ class Dynamic
* @param $did
* @return mixed
*/
public static function getDynamicDetail($did)
public static function getDynamicDetail($did): mixed
{
$url = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail";
$payload = [
@ -226,7 +226,7 @@ class Dynamic
* @param $did
* @return mixed
*/
public static function getLotteryNotice($did)
public static function getLotteryNotice($did): mixed
{
$url = 'https://api.vc.bilibili.com/lottery_svr/v1/lottery_svr/lottery_notice';
$payload = [
@ -240,9 +240,9 @@ class Dynamic
* 获取个人动态TAB列表
* @param int $uid
* @param int $type_list
* @return array|mixed
* @return mixed
*/
public static function getDynamicTab(int $uid = 0, int $type_list = 268435455)
public static function getDynamicTab(int $uid = 0, int $type_list = 268435455): mixed
{
$uid = $uid == 0 ? getUid() : $uid;
$url = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new";
@ -283,8 +283,8 @@ class Dynamic
$custom_words = empty($words = getConf('filter_words', 'dynamic')) ? [] : explode(',', $words);
$total_words = array_merge($default_words, $custom_words, $common_words);
foreach ($total_words as $word) {
if (strpos($item['desc'], $word) !== false) {
Log::warning("当前动态#{$item['did']}触发关键字过滤 {$word}");
if (str_contains($item['desc'], $word)) {
Log::warning("当前动态#{$item['did']}触发关键字过滤 $word");
return true;
}
}
@ -296,7 +296,7 @@ class Dynamic
}
// 过滤粉丝数量
if (($num = Live::getMidFollower((int)$item['uid'])) < getConf('min_fans_num', 'dynamic')) {
Log::warning("当前动态#{$item['did']}触发UP粉丝数量过滤 {$num}");
Log::warning("当前动态#{$item['did']}触发UP粉丝数量过滤 $num");
return true;
}
return false;

View File

@ -27,20 +27,20 @@ class Forward
{
use TimeLock;
public static $default_follows = [];
public static array $default_follows = [];
public static $un_follows = [];
public static $del_dynamic = [];
public static array $un_follows = [];
public static array $del_dynamic = [];
public static $already = [];
public static array $already = [];
private static $group_name = "氪可改命";
private static string $group_name = "氪可改命";
private static $group_id = null;
private static int|null $group_id = null;
private static $draw_follow = [];
private static array $draw_follow = [];
private static $repository = APP_DATA_PATH . 'reply_words.json';
private static string $repository = APP_DATA_PATH . 'reply_words.json';
public static function run()
@ -86,17 +86,17 @@ class Forward
if (isset(self::$already[$did])) {
//重复
Log::info("[动态抽奖]-已转发 跳过: {$did} {$article['uid']}");
Log::info("[动态抽奖]-已转发 跳过: $did {$article['uid']}");
continue;
}
// 评论
Log::info("[动态抽奖]-评论: {$did} {$article['rid']}");
Log::info("[动态抽奖]-评论: $did {$article['rid']}");
if (Dynamic::dynamicReplyAdd($article['rid'], self::getReplyMsg())) {
// 转发
Log::info("[动态抽奖]-转发: {$did}");
Log::info("[动态抽奖]-转发: $did");
if (Dynamic::dynamicRepost($did, self::getReplyMsg())) {
// 关注
Log::info("[动态抽奖]-关注: {$did} {$article['uid']}");
Log::info("[动态抽奖]-关注: $did {$article['uid']}");
self::addToGroup($article['uid']); //
self::$already[$did] = 1;
}
@ -122,20 +122,20 @@ class Forward
if (isset($card["item"]["miss"]) && $card["item"]["miss"] == 1) {
$flag = true;
$msg = "[动态抽奖]-删除动态 源动态已删除 {$did}";
$msg = "[动态抽奖]-删除动态 源动态已删除 $did";
}
if (isset($card["origin_extension"]['lott'])) {
$lott = json_decode($card["origin_extension"]["lott"], true);
if (isset($lott["lottery_time"]) && $lott["lottery_time"] <= time()) {
$flag = true;
$msg = "[动态抽奖]-删除动态 抽奖已过期 {$did}";
$msg = "[动态抽奖]-删除动态 抽奖已过期 $did";
}
}
if (isset($card["item"]["orig_dy_id"])) {
$ret = Dynamic::getLotteryNotice($card["item"]["orig_dy_id"]);
if (isset($ret['data']['lottery_time']) && $ret['data']['lottery_time'] <= time()) {
$flag = true;
$msg = "[动态抽奖]-删除动态 抽奖已过期 {$did}";
$msg = "[动态抽奖]-删除动态 抽奖已过期 $did";
}
}
@ -175,7 +175,7 @@ class Forward
foreach (self::$un_follows as $uid) {
// 非转发抽奖动态关注的up 不取关
if (isset(self::$draw_follow[$uid])) {
Log::info("[动态抽奖]-未中奖-取关 {$uid}");
Log::info("[动态抽奖]-未中奖-取关 $uid");
User::setUserFollow($uid, true);
}
}
@ -193,7 +193,7 @@ class Forward
}
$r = User::fetchTagFollowings($gid);
foreach ($r as $uid) {
Log::info("[清除抽奖组关注] : {$uid}");
Log::info("[清除抽奖组关注] : $uid");
User::setUserFollow($uid, true);
}
}
@ -215,8 +215,8 @@ class Forward
if (!isset($card['item']['content']) || !$msg) {
continue;
}
if (strpos($card['item']['content'], $msg) !== false) {
Log::info("[删除所有动态] 删除动态 {$did}");
if (str_contains($card['item']['content'], $msg)) {
Log::info("[删除所有动态] 删除动态 $did");
Dynamic::removeDynamic($did);
}
}
@ -290,7 +290,7 @@ class Forward
shuffle($data);
$msg = array_pop($data);
}
Log::info("已将自动回复改为\"{$msg}\"");
Log::info("已将自动回复改为\"$msg\"");
return $msg;
}

View File

@ -76,6 +76,7 @@ class GiftHeart
}
return false;
}
return false;
}
}

View File

@ -19,9 +19,9 @@ class GiftRaffle extends BaseRaffle
const ACTIVE_TITLE = '活动礼物';
const ACTIVE_SWITCH = 'live_gift';
protected static $wait_list = [];
protected static $finish_list = [];
protected static $all_list = [];
protected static array $wait_list = [];
protected static array $finish_list = [];
protected static array $all_list = [];
/**
* @use 解析数据
@ -98,9 +98,9 @@ class GiftRaffle extends BaseRaffle
/**
* @use 解析抽奖信息
* @param array $results
* @return void
* @return mixed
*/
protected static function parseLottery(array $results)
protected static function parseLottery(array $results):mixed
{
foreach ($results as $result) {
$data = $result['source'];
@ -123,5 +123,6 @@ class GiftRaffle extends BaseRaffle
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: " . isset($de_raw['msg']) ? $de_raw['msg'] : $de_raw);
}
}
return '';
}
}

View File

@ -18,13 +18,13 @@ class GiftSend
{
use TimeLock;
protected static $uid = 0;
protected static $tid = 0;
protected static $r_uid = 0;
protected static $room_id = 0;
protected static $short_id = 0;
protected static $room_list = [];
protected static $medal_list = [];
protected static int $uid = 0;
protected static int $tid = 0;
protected static int $r_uid = 0;
protected static int $room_id = 0;
protected static int $short_id = 0;
protected static array $room_list = [];
protected static array $medal_list = [];
public static function run()
@ -77,12 +77,12 @@ class GiftSend
if (!in_array($gift['gift_id'], [1, 6])) {
continue;
}
Log::notice("直播间 {$room_id} 需赠送亲密度 {$total_intimacy} 剩余亲密度 " . ($total_intimacy - $current_intimacy));
Log::notice("直播间 $room_id 需赠送亲密度 $total_intimacy 剩余亲密度 " . ($total_intimacy - $current_intimacy));
$amt = self::calcAmt($gift, $total_intimacy - $current_intimacy);
self::sendGift($gift, $amt);
$current_intimacy += ($gift['gift_id'] == 6) ? ($amt * 10) : $amt;
if (!($current_intimacy - $total_intimacy)) {
Log::notice("直播间 {$room_id} 亲密度 {$total_intimacy} 送满啦~送满啦~");
Log::notice("直播间 $room_id 亲密度 $total_intimacy 送满啦~送满啦~");
break;
}
}
@ -275,7 +275,7 @@ class GiftSend
if (isset($data['code']) && $data['code']) {
Log::warning('送礼失败!', ['msg' => $data['message']]);
} else {
Log::notice("成功向 {$payload['biz_id']} 投喂了 {$amt}{$value['gift_name']}");
Log::notice("成功向 {$payload['biz_id']} 投喂了 $amt{$value['gift_name']}");
}
}
}

View File

@ -19,9 +19,9 @@ class GuardRaffle extends BaseRaffle
const ACTIVE_TITLE = '总督舰长';
const ACTIVE_SWITCH = 'live_guard';
protected static $wait_list = [];
protected static $finish_list = [];
protected static $all_list = [];
protected static array $wait_list = [];
protected static array $finish_list = [];
protected static array $all_list = [];
/**
* @use 解析数据
@ -112,9 +112,9 @@ class GuardRaffle extends BaseRaffle
/**
* @use 解析抽奖信息
* @param array $results
* @return void
* @return mixed
*/
protected static function parseLottery(array $results)
protected static function parseLottery(array $results):mixed
{
foreach ($results as $result) {
$data = $result['source'];
@ -132,6 +132,7 @@ class GuardRaffle extends BaseRaffle
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: " . isset($de_raw['msg']) ? $de_raw['msg'] : $de_raw);
}
}
return '';
}
}

View File

@ -13,16 +13,17 @@ namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
use JetBrains\PhpStorm\ArrayShape;
class Judge
{
use TimeLock;
private static $retry_time = 0;
private static $wait_case_id = 0;
private static $wait_time = 0;
private static $min_ok_pct = 1;
private static $max_ok_pct = 0;
private static int $retry_time = 0;
private static int $wait_case_id = 0;
private static int $wait_time = 0;
private static int $min_ok_pct = 1;
private static int $max_ok_pct = 0;
public static function run()
{
@ -63,7 +64,7 @@ class Judge
self::$max_ok_pct = max(self::$max_ok_pct, $ok_pct);
// user.info('更新统计投票波动情况')
}
// Log::info("案件 {$case_id} 已经等待" . self::$wait_time . "s统计波动区间为" . self::$min_ok_pct . "-" . self::$max_ok_pct);
// Log::info("案件 $case_id 已经等待" . self::$wait_time . "s统计波动区间为" . self::$min_ok_pct . "-" . self::$max_ok_pct);
if (is_null($advice)) {
if (self::$wait_time >= 1200) {
// 如果case判定中波动很小则表示趋势基本一致
@ -73,10 +74,10 @@ class Judge
$advice1 = self::judgeAdvice($num_judged, self::$min_ok_pct);
$advice = ($advice0 == $advice1) ? $advice0 : null;
}
Log::info("判定结果 {$advice}");
Log::info("判定结果 $advice");
} else {
$sleep_wait_time = ($num_judged < 300) ? 200 : 60;
Log::info("案件 {$case_id} 暂无法判定,{$sleep_wait_time}S 后重新尝试");
Log::info("案件 $case_id 暂无法判定,{$sleep_wait_time}S 后重新尝试");
self::$wait_time += $sleep_wait_time;
self::$retry_time = $sleep_wait_time + time();
self::$wait_case_id = $case_id;
@ -86,7 +87,7 @@ class Judge
// 如果还不行就放弃
$decision = !is_null($advice) ? $advice : 3;
$dicision_info = ($decision == 3) ? '作废票' : '有效票';
Log::info("案件 {$case_id} 的投票结果:{$dicision_info}({$decision})");
Log::info("案件 $case_id 的投票结果:$dicision_info($decision)");
self::juryVote($case_id, $decision);
self::initParams();
return true;
@ -155,17 +156,17 @@ class Judge
// {"code":25012,"message":"请勿重复投票","ttl":1}
$de_raw = json_decode($raw, true);
if (isset($de_raw['code']) && $de_raw['code']) {
Log::warning("案件 {$case_id} 投票失败 {$raw}");
Log::warning("案件 $case_id 投票失败 $raw");
} else {
Log::notice("案件 {$case_id} 投票成功 {$raw}");
Log::notice("案件 $case_id 投票成功 $raw");
}
}
/**
* @use 案件获取
* @return mixed|null
* @return mixed
*/
private static function caseObtain()
private static function caseObtain(): mixed
{
$url = 'https://api.bilibili.com/x/credit/jury/caseObtain';
$payload = [
@ -184,19 +185,19 @@ class Judge
self::setLock(self::timing(10));
return null;
case 25008:
Log::info("暂时没有新的案件需要审理~ {$raw}");
Log::info("暂时没有新的案件需要审理~ $raw");
return null;
case 25014:
Log::info("今日案件已审满,感谢您对社区的贡献!明天再来看看吧~");
self::setLock(self::timing(7, 0, 0, true));
return null;
default:
Log::info("获取案件失败~ {$raw}");
Log::info("获取案件失败~ $raw");
return null;
}
} else {
$case_id = $de_raw['data']['id'];
Log::info("获取到案件 {$case_id} ~");
Log::info("获取到案件 $case_id ~");
return $case_id;
}
}
@ -206,11 +207,12 @@ class Judge
* @param $case_id
* @return array
*/
#[ArrayShape(['num_voted' => "mixed", 'ok_percent' => "float|int"])]
private static function judgementVote($case_id): array
{
$url = 'https://api.bilibili.com/x/credit/jury/juryCase';
$headers = [
'Referer' => "https://www.bilibili.com/judgement/vote/{$case_id}"
'Referer' => "https://www.bilibili.com/judgement/vote/$case_id"
];
$payload = [
'callback' => "jQuery1720" . self::randInt() . "_" . time(),
@ -230,7 +232,7 @@ class Judge
$num_voted = $vote_break + $vote_delete + $vote_rule;
$ok_percent = $num_voted ? ($vote_rule / $num_voted) : 0;
// 言论合理比例 {$ok_percent}
Log::info("案件 {$case_id} 目前已投票 {$num_voted}");
Log::info("案件 $case_id 目前已投票 $num_voted");
return [
'num_voted' => $num_voted,
'ok_percent' => $ok_percent
@ -245,7 +247,7 @@ class Judge
private static function randInt(int $max = 17): string
{
$temp = [];
foreach (range(1, $max) as $_) {
foreach (range(1, $max) as $ignored) {
array_push($temp, mt_rand(0, 9));
}
return implode("", $temp);
@ -267,7 +269,7 @@ class Judge
* @use 获取案例数据|风纪检测
* @return bool
*/
private static function judgementIndex()
private static function judgementIndex(): bool
{
$url = 'https://api.bilibili.com/x/credit/jury/caseList';
$headers = [

View File

@ -13,6 +13,7 @@ namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
use JetBrains\PhpStorm\ArrayShape;
class Live
{
@ -25,7 +26,7 @@ class Live
public static function fetchLiveAreas(): array
{
$areas = [];
$url = "http://api.live.bilibili.com/room/v1/Area/getList";
$url = "https://api.live.bilibili.com/room/v1/Area/getList";
$payload = [];
$raw = Curl::get('other', $url, $payload);
$de_raw = json_decode($raw, true);
@ -46,6 +47,7 @@ class Live
* @param $area_id
* @return array
*/
#[ArrayShape(['area_id' => "", 'room_id' => "int|mixed"])]
public static function areaToRid($area_id): array
{
$url = "https://api.live.bilibili.com/room/v1/area/getRoomList";
@ -101,28 +103,56 @@ class Live
/**
* @use 获取直播房间号
* @param $room_id
* @return false|mixed
* @param bool $uid
* @return mixed
*/
public static function getRealRoomID($room_id)
public static function getRealRoomID($room_id, bool $uid = false): mixed
{
$data = self::getRoomInfoV1($room_id);
if (!isset($data['code']) || !isset($data['data'])) {
return false;
$room_infos = [];
// 缓存开始 如果存在就赋值 否则默认值
if ($temp = getCache('room_infos')) {
$room_infos = $temp;
}
if ($data['code']) {
Log::warning($room_id . ' : ' . $data['msg']);
return false;
// 取缓存
if (isset($room_infos[strval($room_id)])) {
$data = $room_infos[strval($room_id)];
} else {
// 默认数据
$_data = ['uid' => false, 'room_id' => false];
// TODO 优化
$data = self::getRoomInfoV1($room_id);
if (!isset($data['code']) || !isset($data['data'])) {
// 访问错误
$data = $_data;
} elseif ($data['code']) {
// 访问错误
$data = $_data;
Log::warning($room_id . ' : ' . $data['msg']);
} elseif ($data['data']['is_hidden']) {
// 隐藏
$data = $_data;
} elseif ($data['data']['is_locked']) {
// 锁定
$data = $_data;
} elseif ($data['data']['encrypted']) {
// 加密
$data = $_data;
} else {
// 有效
$data = [
'uid' => $data['data']['uid'],
'room_id' => $data['data']['room_id'],
];
}
// 推入缓存前
$room_infos[strval($room_id)] = $data;
}
if ($data['data']['is_hidden']) {
return false;
}
if ($data['data']['is_locked']) {
return false;
}
if ($data['data']['encrypted']) {
return false;
}
return $data['data']['room_id'];
// 缓存结束 需要的数据的放进缓存
setCache('room_infos', $room_infos);
// 如果需要UID
if ($uid) return $data;
// 否
return $data['room_id'];
}
/**
@ -177,6 +207,7 @@ class Live
* @param $room_id
* @return array
*/
#[ArrayShape(['addr' => "mixed|string", 'token' => "mixed|string"])]
public static function getDanMuInfo($room_id): array
{
$data = self::getDanMuConf($room_id);
@ -262,7 +293,7 @@ class Live
];
$headers = [
'origin' => 'https://live.bilibili.com',
'referer' => "https://live.bilibili.com/{$room_id}"
'referer' => "https://live.bilibili.com/$room_id"
];
$raw = Curl::post('pc', $url, $payload, $headers);
// {"code":0,"data":[],"message":"","msg":""}
@ -400,7 +431,7 @@ class Live
if (isset($data['code']) && $data['code']) {
Log::warning('送礼失败!', ['msg' => $data['message']]);
} else {
Log::notice("成功向 {$payload['biz_id']} 投喂了 {$num}{$gift['gift_name']}");
Log::notice("成功向 {$payload['biz_id']} 投喂了 $num{$gift['gift_name']}");
}
}

View File

@ -13,15 +13,20 @@ use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
use BiliHelper\Tool\Common;
use JetBrains\PhpStorm\ArrayShape;
use JetBrains\PhpStorm\NoReturn;
class Login
{
use TimeLock;
// 账密
private static $username;
private static $password;
private static string $username;
private static string $password;
/**
* @throws \Jelix\IniFile\IniException
*/
public static function run()
{
if (self::getLock()) {
@ -47,6 +52,7 @@ class Login
/**
* @use 登录控制中心
* @throws \Jelix\IniFile\IniException
*/
private static function login()
{
@ -73,6 +79,7 @@ class Login
/**
* @use 检查登录
* @throws \Jelix\IniFile\IniException
*/
private static function checkLogin()
{
@ -90,6 +97,7 @@ class Login
/**
* @use 保持认证
* @return bool
* @throws \Jelix\IniFile\IniException
*/
private static function keepAuth(): bool
{
@ -132,6 +140,7 @@ class Login
/**
* @use 刷新Token
* @throws \Jelix\IniFile\IniException
*/
private static function refreshToken(): bool
{
@ -179,7 +188,7 @@ class Login
/**
* @use 获取验证码
* @return array|string[]
* @return array
*/
private static function getCaptcha(): array
{
@ -210,6 +219,7 @@ class Login
* @param array $captcha
* @return array
*/
#[ArrayShape(['validate' => "mixed", 'challenge' => "mixed"])]
private static function ocrCaptcha(array $captcha): array
{
$url = 'https://captcha-v1.mudew.com:19951/';
@ -236,14 +246,15 @@ class Login
* @param string $validate
* @param string $challenge
* @param string $mode
* @throws \Jelix\IniFile\IniException
*/
private static function accountLogin(string $validate = '', string $challenge = '', string $mode = '账密模式')
{
Log::info("尝试 {$mode} 登录");
Log::info("尝试 $mode 登录");
// $url = 'https://passport.bilibili.com/api/v3/oauth2/login';
$url = 'https://passport.bilibili.com/x/passport-login/oauth2/login';
$payload = [
'seccode' => $validate ? "{$validate}|jordan" : '',
'seccode' => $validate ? "$validate|jordan" : '',
'validate' => $validate,
'challenge' => $challenge,
'permission' => 'ALL',
@ -266,10 +277,11 @@ class Login
/**
* @use 短信登录
* @param string $mode
* @throws \Jelix\IniFile\IniException
*/
private static function smsLogin(string $mode = '短信模式')
{
Log::info("尝试 {$mode} 登录");
Log::info("尝试 $mode 登录");
if (getConf('phone', 'login.check')) {
self::checkPhone(self::$username);
}
@ -293,7 +305,7 @@ class Login
* @param int $max_char
* @return string
*/
private static function cliInput(string $msg, $max_char = 100): string
private static function cliInput(string $msg, int $max_char = 100): string
{
$stdin = fopen('php://stdin', 'r');
echo '# ' . $msg;
@ -307,11 +319,12 @@ class Login
* @param string $phone
* @return array
*/
#[ArrayShape(['cid' => "mixed", 'tel' => "string", 'statistics' => "string", 'captcha_key' => "mixed"])]
private static function sendSms(string $phone): array
{
$url = 'https://passport.bilibili.com//x/passport-login/sms/send';
$payload = [
'cid' => getConf('country_code', 'login.country') ,
'cid' => getConf('country_code', 'login.country'),
'tel' => $phone,
'statistics' => '{"appId":1,"platform":3,"version":"6.32.0","abtest":""}',
];
@ -324,7 +337,7 @@ class Login
$payload['captcha_key'] = $de_raw['data']['captcha_key'];
return $payload;
}
Log::error("短信验证码发送失败 {$raw}");
Log::error("短信验证码发送失败 $raw");
die();
}
@ -333,6 +346,7 @@ class Login
* @param $mode
* @param $code
* @param $data
* @throws \Jelix\IniFile\IniException
*/
private static function loginAfter($mode, $code, $data)
{
@ -349,11 +363,9 @@ class Login
case 2:
// 异常高危
self::loginFail($mode, $data['data']['message']);
break;
default:
// 未知错误
self::loginFail($mode, '未知错误: ' . $data['data']['message']);
break;
}
} else {
// 正常登录
@ -363,19 +375,15 @@ class Login
case -105:
// 需要验证码
self::loginFail($mode, '此次登录需要验证码或' . $data['message']);
break;
case -629:
// 密码错误
self::loginFail($mode, $data['message']);
break;
case -2100:
// 验证手机号
self::loginFail($mode, '账号启用了设备锁或异地登录需验证手机号');
break;
default:
// 未知错误
self::loginFail($mode, '未知错误: ' . $data['message']);
break;
}
}
@ -384,10 +392,11 @@ class Login
* @use 登录成功
* @param $mode
* @param $data
* @throws \Jelix\IniFile\IniException
*/
private static function loginSuccess($mode, $data)
{
Log::info("{$mode} 登录成功");
Log::info("$mode 登录成功");
self::successHandle($data);
Log::info('生成信息配置完毕');
}
@ -395,6 +404,7 @@ class Login
/**
* @use 刷新成功
* @param $data
* @throws \Jelix\IniFile\IniException
*/
private static function refreshSuccess($data)
{
@ -406,6 +416,7 @@ class Login
/**
* @use 成功处理
* @param $data
* @throws \Jelix\IniFile\IniException
*/
private static function successHandle($data)
{
@ -424,9 +435,10 @@ class Login
* @param $mode
* @param $data
*/
#[NoReturn]
private static function loginFail($mode, $data)
{
Log::error("{$mode} 登录失败", ['msg' => $data]);
Log::error("$mode 登录失败", ['msg' => $data]);
die();
}
@ -436,7 +448,8 @@ class Login
*/
private static function checkPhone(string $phone)
{
if (!preg_match("/^1[3456789]{1}\d{9}$/", $phone)) {
// /^1[3456789]{1}\d{9}$/
if (!preg_match("/^1[3456789]\d{9}$/", $phone)) {
Log::error("当前用户名不是有效手机号格式");
die();
}
@ -449,12 +462,13 @@ class Login
* @param string $section
* @param bool $print
* @param bool $hide
* @throws \Jelix\IniFile\IniException
*/
private static function saveConfig(string $key, string $value, string $section, $print = true, $hide = true)
private static function saveConfig(string $key, string $value, string $section, bool $print = true, bool $hide = true)
{
setConf($key, $value, $section);
if ($print) {
Log::info(" > {$key}: " . ($hide ? Common::replaceStar($value, 6, 6) : $value));
Log::info(" > $key: " . ($hide ? Common::replaceStar($value, 6, 6) : $value));
}
}
@ -475,6 +489,7 @@ class Login
/**
* @use 清除已有
* @throws \Jelix\IniFile\IniException
*/
private static function clearAccount()
{
@ -507,6 +522,7 @@ class Login
/**
* @use 验证码登录
* @param string $mode
* @throws \Jelix\IniFile\IniException
*/
private static function captchaLogin(string $mode = '验证码模式')
{

View File

@ -13,6 +13,7 @@ namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
use JetBrains\PhpStorm\ArrayShape;
class MainSite
{
@ -47,7 +48,7 @@ class MainSite
$headers = [
'Host' => "api.bilibili.com",
'Origin' => "https://www.bilibili.com",
'Referer' => "https://www.bilibili.com/video/av{$aid}",
'Referer' => "https://www.bilibili.com/video/av$aid",
'User-Agent' => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
];
// {"code":34005,"message":"超过投币上限啦~","ttl":1,"data":{"like":false}}
@ -55,10 +56,10 @@ class MainSite
$raw = Curl::post('app', $url, Sign::common($payload), $headers);
$de_raw = json_decode($raw, true);
if ($de_raw['code'] == 0) {
Log::notice("主站任务: av{$aid} 投币成功 {$de_raw['code']} MSG -> {$de_raw['message']}");
Log::notice("主站任务: av$aid 投币成功 {$de_raw['code']} MSG -> {$de_raw['message']}");
return true;
} else {
Log::warning("主站任务: av{$aid} 投币失败 CODE -> {$de_raw['code']} MSG -> {$de_raw['message']}");
Log::warning("主站任务: av$aid 投币失败 CODE -> {$de_raw['code']} MSG -> {$de_raw['message']}");
return false;
}
}
@ -83,7 +84,7 @@ class MainSite
if ($log_date != $now_date) {
break;
}
if (strpos($log['reason'], "打赏") !== false) {
if (str_contains($log['reason'], "打赏")) {
switch ($log['delta']) {
case -1:
$coins += 1;
@ -113,7 +114,7 @@ class MainSite
$stock_num = self::getCoin();
// 实际数量 处理硬币库存少于预计数量
$actual_num = intval($estimate_num > $stock_num ? $stock_num : $estimate_num) - self::coinLog();
Log::info("当前硬币库存 {$stock_num} 预计投币 {$estimate_num} 实际投币 {$actual_num}");
Log::info("当前硬币库存 $stock_num 预计投币 $estimate_num 实际投币 $actual_num");
// 上限
if ($actual_num <= 0) {
Log::notice('今日投币上限已满');
@ -361,6 +362,7 @@ class MainSite
* @use 解析AID到CID
* @return array
*/
#[ArrayShape(['aid' => "string", 'cid' => "mixed", 'duration' => "mixed"])]
private static function parseAid(): array
{
while (true) {

View File

@ -20,9 +20,9 @@ class MaterialObject
use TimeLock;
use FilterWords;
private static $invalid_aids = [];
private static $start_aid = 0;
private static $end_aid = 0;
private static array $invalid_aids = [];
private static int $start_aid = 0;
private static int $end_aid = 0;
public static function run()
{
@ -46,7 +46,7 @@ class MaterialObject
self::loadJsonData();
$sensitive_words = self::$store->get("MaterialObject.sensitive");
foreach ($sensitive_words as $word) {
if (strpos($title, $word) !== false) {
if (str_contains($title, $word)) {
return true;
}
}
@ -57,9 +57,9 @@ class MaterialObject
* @use 抽奖盒子状态
* @param int $aid
* @param string $reply
* @return array|bool|mixed
* @return mixed
*/
private static function boxStatus(int $aid, $reply = 'bool')
private static function boxStatus(int $aid, string $reply = 'bool'): mixed
{
// $url = 'https://api.live.bilibili.com/lottery/v1/box/getStatus';
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v2/Box/getStatus';
@ -93,6 +93,11 @@ class MaterialObject
*/
private static function fetchLottery(): array
{
// 缓存开始 如果存在就赋值 否则默认值
if ($temp = getCache('invalid_aids')) {
self::$invalid_aids = $temp;
}
$lottery_list = [];
$max_probe = 10;
$probes = range(self::$start_aid, self::$end_aid);
@ -132,6 +137,9 @@ class MaterialObject
'num' => $round_num,
]);
}
// 缓存结束 需要的数据的放进缓存
setCache('invalid_aids', self::$invalid_aids);
return $lottery_list;
}
@ -168,7 +176,7 @@ class MaterialObject
foreach ($lottery_list as $lottery) {
$aid = $lottery['aid'];
$num = $lottery['num'];
Log::notice("实物抽奖 {$aid} 轮次 {$num} 可参与抽奖~");
Log::notice("实物抽奖 $aid 轮次 $num 可参与抽奖~");
// $url = 'https://api.live.bilibili.com/lottery/v1/Box/draw';
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v2/Box/draw';
$payload = [
@ -178,9 +186,9 @@ class MaterialObject
$raw = Curl::get('pc', $url, $payload);
$de_raw = json_decode($raw, true);
if ($de_raw['code'] == 0) {
Log::notice("实物抽奖 {$aid} 轮次 {$num} 参与抽奖成功~");
Log::notice("实物抽奖 $aid 轮次 $num 参与抽奖成功~");
} else {
Log::notice("实物抽奖 {$aid} 轮次 {$num} {$de_raw['msg']}~");
Log::notice("实物抽奖 $aid 轮次 $num {$de_raw['msg']}~");
}
}
return true;

View File

@ -43,12 +43,12 @@ class Notice
private static function filterResultWords(string $result): bool
{
self::loadJsonData();
$default_words = self::$store->get("Notice.default");;
$default_words = self::$store->get("Notice.default");
$custom_words = explode(',', getConf('filter_words', 'notify'));
$total_words = array_merge($default_words, $custom_words);
foreach ($total_words as $word) {
if (empty($word)) continue;
if (strpos($result, $word) !== false) {
if (str_contains($result, $word)) {
return true;
}
}
@ -65,86 +65,60 @@ class Notice
private static function sendInfoHandle(string $type, string $uname, string $result): bool
{
$now_time = date('Y-m-d H:i:s');
switch ($type) {
case 'update':
$info = [
'title' => '程序更新通知',
'content' => "[{$now_time}] 用户: {$uname} 程序更新通知: {$result}"
];
break;
case 'anchor':
$info = [
'title' => '天选时刻获奖记录',
'content' => "[{$now_time}] 用户: {$uname} 在天选时刻中获得: {$result}"
];
break;
case 'raffle':
$info = [
'title' => '实物奖励获奖纪录',
'content' => "[{$now_time}] 用户: {$uname} 在实物奖励中获得: {$result}"
];
break;
case 'gift':
$info = [
'title' => '活动礼物获奖纪录',
'content' => "[{$now_time}] 用户: {$uname} 在活动礼物中获得: {$result}"
];
break;
case 'storm':
$info = [
'title' => '节奏风暴获奖纪录',
'content' => "[{$now_time}] 用户: {$uname} 在节奏风暴中获得: {$result}"
];
break;
case 'cookieRefresh':
$info = [
'title' => 'Cookie刷新',
'content' => "[{$now_time}] 用户: {$uname} 刷新Cookie: {$result}"
];
break;
case 'todaySign':
$info = [
'title' => '每日签到',
'content' => "[{$now_time}] 用户: {$uname} 签到: {$result}"
];
break;
case 'banned':
$info = [
'title' => '任务小黑屋',
'content' => "[{$now_time}] 用户: {$uname} 小黑屋: {$result}"
];
break;
case 'error':
$info = [
'title' => '程序运行错误',
'content' => "[{$now_time}] 用户: {$uname} 错误详情: {$result}"
];
break;
case 'key_expired':
$info = [
'title' => '监控KEY异常',
'content' => "[{$now_time}] 用户: {$uname} 监控KEY到期或者错误请及时查错或续期后重试哦~"
];
break;
case 'capsule_lottery':
$info = [
'title' => '直播扭蛋抽奖活动',
'content' => "[{$now_time}] 用户: {$uname} 详情: {$result}"
];
break;
case 'activity_lottery':
$info = [
'title' => '主站九宫格抽奖活动',
'content' => "[{$now_time}] 用户: {$uname} 详情: {$result}"
];
break;
default:
$info = [
'title' => '推送消息异常记录',
'content' => "[{$now_time}] 用户: {$uname} 推送消息key错误: {$type}->{$result}"
];
break;
}
$info = match ($type) {
'update' => [
'title' => '程序更新通知',
'content' => "[$now_time] 用户: $uname 程序更新通知: $result"
],
'anchor' => [
'title' => '天选时刻获奖记录',
'content' => "[$now_time] 用户: $uname 在天选时刻中获得: $result"
],
'raffle' => [
'title' => '实物奖励获奖纪录',
'content' => "[$now_time] 用户: $uname 在实物奖励中获得: $result"
],
'gift' => [
'title' => '活动礼物获奖纪录',
'content' => "[$now_time] 用户: $uname 在活动礼物中获得: $result"
],
'storm' => [
'title' => '节奏风暴获奖纪录',
'content' => "[$now_time] 用户: $uname 在节奏风暴中获得: $result"
],
'cookieRefresh' => [
'title' => 'Cookie刷新',
'content' => "[$now_time] 用户: $uname 刷新Cookie: $result"
],
'todaySign' => [
'title' => '每日签到',
'content' => "[$now_time] 用户: $uname 签到: $result"
],
'banned' => [
'title' => '任务小黑屋',
'content' => "[$now_time] 用户: $uname 小黑屋: $result"
],
'error' => [
'title' => '程序运行错误',
'content' => "[$now_time] 用户: $uname 错误详情: $result"
],
'key_expired' => [
'title' => '监控KEY异常',
'content' => "[$now_time] 用户: $uname 监控KEY到期或者错误请及时查错或续期后重试哦~"
],
'capsule_lottery' => [
'title' => '直播扭蛋抽奖活动',
'content' => "[$now_time] 用户: $uname 详情: $result"
],
'activity_lottery' => [
'title' => '主站九宫格抽奖活动',
'content' => "[$now_time] 用户: $uname 详情: $result"
],
default => [
'title' => '推送消息异常记录',
'content' => "[$now_time] 用户: $uname 推送消息key错误: $type->$result"
],
};
self::sendLog($info);
return true;
@ -181,7 +155,7 @@ class Notice
/**
* @use DingTalkbot推送
* @doc https://developers.dingtalk.com/document/app/document-upgrade-notice#/serverapi2/qf2nxq
* @doc https://developers.dingtalk.com/document/robots/custom-robot-access
* @param array $info
*/
private static function dingTalkSend(array $info)
@ -203,7 +177,7 @@ class Notice
if ($de_raw['errcode'] == 0) {
Log::notice("推送消息成功: {$de_raw['errmsg']}");
} else {
Log::warning("推送消息失败: {$raw}");
Log::warning("推送消息失败: $raw");
}
}
@ -226,7 +200,7 @@ class Notice
if ($de_raw['ok'] && array_key_exists('message_id', $de_raw['result'])) {
Log::notice("推送消息成功: MSG_ID->{$de_raw['result']['message_id']}");
} else {
Log::warning("推送消息失败: {$raw}");
Log::warning("推送消息失败: $raw");
}
}
@ -249,7 +223,7 @@ class Notice
if ($de_raw['errno'] == 0) {
Log::notice("推送消息成功: {$de_raw['errmsg']}");
} else {
Log::warning("推送消息失败: {$raw}");
Log::warning("推送消息失败: $raw");
}
}
@ -273,7 +247,7 @@ class Notice
if ($de_raw['code'] == 0) {
Log::notice("推送消息成功: {$de_raw['data']['pushid']}");
} else {
Log::warning("推送消息失败: {$raw}");
Log::warning("推送消息失败: $raw");
}
}
@ -285,7 +259,7 @@ class Notice
private static function pushPlusSend(array $info)
{
Log::info('使用PushPlus酱推送消息');
$url = 'http://www.pushplus.plus/send';
$url = 'https://www.pushplus.plus/send';
$payload = [
'token' => getConf('token', 'notify.pushplus'),
'title' => $info['title'],
@ -300,7 +274,7 @@ class Notice
if ($de_raw['code'] == 200) {
Log::notice("推送消息成功: {$de_raw['data']}");
} else {
Log::warning("推送消息失败: {$raw}");
Log::warning("推送消息失败: $raw");
}
}
@ -324,7 +298,7 @@ class Notice
if ($de_raw['retcode'] == 0) {
Log::notice("推送消息成功: {$de_raw['status']}");
} else {
Log::warning("推送消息失败: {$raw}");
Log::warning("推送消息失败: $raw");
}
}
@ -349,7 +323,7 @@ class Notice
if ($de_raw['success'] == true) {
Log::notice("推送消息成功: {$de_raw['data']['msgid']}");
} else {
Log::warning("推送消息失败: {$raw}");
Log::warning("推送消息失败: $raw");
}
}

View File

@ -20,9 +20,9 @@ class PkRaffle extends BaseRaffle
const ACTIVE_TITLE = '主播乱斗';
const ACTIVE_SWITCH = 'live_pk';
protected static $wait_list = [];
protected static $finish_list = [];
protected static $all_list = [];
protected static array $wait_list = [];
protected static array $finish_list = [];
protected static array $all_list = [];
/**
* @use 解析数据
@ -95,9 +95,9 @@ class PkRaffle extends BaseRaffle
/**
* @use 解析抽奖信息
* @param array $results
* @return void
* @return mixed
*/
protected static function parseLottery(array $results)
protected static function parseLottery(array $results):mixed
{
foreach ($results as $result) {
$data = $result['source'];
@ -122,5 +122,6 @@ class PkRaffle extends BaseRaffle
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: {$de_raw['message']}");
}
}
return '';
}
}

View File

@ -18,9 +18,9 @@ class PolishTheMedal
{
use TimeLock;
private static $metal_lock = 0; // 勋章时间锁
private static $fans_medals = []; // 全部勋章
private static $grey_fans_medals = []; // 灰色勋章
private static int $metal_lock = 0; // 勋章时间锁
private static array $fans_medals = []; // 全部勋章
private static array $grey_fans_medals = []; // 灰色勋章
/**
*/
@ -65,7 +65,7 @@ class PolishTheMedal
// 为空
if (is_null($medal)) return;
// 特殊房间处理|央视未开播|CODE -> 11000 MSG -> ''
if (in_array($medal['roomid'], [21686237])) return;
if (in_array($medal['roomid'], [21686237, 0])) return;
Log::info("开始点亮直播间@{$medal['roomid']}的勋章");
// 擦亮

View File

@ -18,23 +18,23 @@ class Schedule
use TimeLock;
// Todo 黑白名单|考虑添加到每个插件内部自动添加|优化RUN逻辑代码
private static $unlock_hour = 24;
private static $unlock_timers = [];
private static $sleep_section = [];
private static int $unlock_hour = 24;
private static array $unlock_timers = [];
private static array $sleep_section = [];
// 日常类
private static $fillable = ['Login', 'Schedule', 'DailyBag', 'Judge', 'MainSite', 'GiftSend', 'DailyTask', 'Silver2Coin', 'ManGa', 'GroupSignIn', 'AwardRecord', 'Statistics'];
private static array $fillable = ['Login', 'Schedule', 'DailyBag', 'Judge', 'MainSite', 'GiftSend', 'DailyTask', 'Silver2Coin', 'ManGa', 'GroupSignIn', 'AwardRecord', 'Statistics'];
// 任务类
private static $guarded_first = ['Barrage', 'GiftHeart', 'Silver', 'MaterialObject'];
private static array $guarded_first = ['Barrage', 'GiftHeart', 'Silver', 'MaterialObject'];
// 监控类
private static $guarded_second = ['AloneTcpClient', 'ZoneTcpClient',];
private static array $guarded_second = ['AloneTcpClient', 'ZoneTcpClient',];
// 抽奖类
private static $guarded_third = ['StormRaffle', 'GuardRaffle', 'PkRaffle', 'GiftRaffle', 'AnchorRaffle'];
private static array $guarded_third = ['StormRaffle', 'GuardRaffle', 'PkRaffle', 'GiftRaffle', 'AnchorRaffle'];
// 特殊 老爷处理
private static $guarded_fourth = ['DoubleHeart'];
private static array $guarded_fourth = ['DoubleHeart'];
// 暂定不做处理,后期看情况再定
private static $release = ['ActivityLottery', 'SmallHeart', 'Competition', 'SmallHeart', 'Forward', 'CapsuleLottery', 'PolishTheMedal'];
private static array $release = ['ActivityLottery', 'SmallHeart', 'Competition', 'SmallHeart', 'Forward', 'CapsuleLottery', 'PolishTheMedal'];
// 暂定不做处理 大会员类
private static $guarded_fifth = ['VipPrivilege', 'BpConsumption'];
private static array $guarded_fifth = ['VipPrivilege', 'BpConsumption'];
public static function run()
@ -56,9 +56,9 @@ class Schedule
self::$sleep_section = empty(self::$sleep_section) ? explode(',', getConf('section', 'sleep')) : self::$sleep_section;
if (!in_array(date('H'), self::$sleep_section)) {
return false;
};
}
self::handleBan('sleep');
};
}
return true;
}
@ -90,13 +90,13 @@ class Schedule
* @param $action
* @param string $classname
*/
private static function handleBan($action, $classname = '')
private static function handleBan($action, string $classname = '')
{
switch ($action) {
// 休眠
case 'sleep':
foreach (self::$fillable as $classname) {
Log::info("插件 {$classname} 白名单,保持当前状态继续");
Log::info("插件 $classname 白名单,保持当前状态继续");
}
$unlock_time = 60 * 60;
self::$unlock_hour = date('H');
@ -112,10 +112,10 @@ class Schedule
// 访问拒绝 统一时间 第二天0点
$unlock_time = strtotime(date("Y-m-d", strtotime("+1 day", time()))) - time();
self::stopProc([$classname], $unlock_time);
Log::warning("{$classname} 任务拒绝访问,暂停任务,自动开启!");
Log::warning("$classname 任务拒绝访问,暂停任务,自动开启!");
// 推送被ban信息
$time = floor($unlock_time / 60 / 60);
Notice::push('banned', "任务 {$classname} 暂停,{$time} 小时后自动恢复!");
Notice::push('banned', "任务 $classname 暂停,$time 小时后自动恢复!");
break;
// 特殊类
case 'special':
@ -139,7 +139,7 @@ class Schedule
private static function stopProc(array $classname_list, int $unlock_time, bool $force = false)
{
foreach ($classname_list as $classname) {
Log::info("插件 {$classname} 黑名单,锁定状态将于" . date("Y-m-d H:i", time() + $unlock_time) . "解除");
Log::info("插件 $classname 黑名单,锁定状态将于" . date("Y-m-d H:i", time() + $unlock_time) . "解除");
// 强制 无视小黑屋设定
if ($force) {
call_user_func(array(__NAMESPACE__ . '\\' . $classname, 'setPauseStatus'), false);

View File

@ -10,36 +10,8 @@
namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
class Sign
{
// /**
// * @use 登录
// * @param $payload
// * @return array
// */
// public static function login($payload)
// {
// # 云视听 TV
// $appkey = '4409e2ce8ffd12b8';
// $appsecret = '59b43e04ad6965f34319062b478f83dd';
//
// $default = [
// 'access_key' => getAccessToken()
// 'actionKey' => 'appkey',
// 'appkey' => $appkey,
// 'build' => 101800,
// 'device' => 'android',
// 'mobi_app' => 'android_tv_yst',
// 'platform' => 'android',
// 'ts' => time(),
// ];
// $payload = array_merge($payload, $default);
// return self::encryption($payload, $appsecret);
// }
/**
* @use 登录
* @param $payload
@ -48,22 +20,22 @@ class Sign
public static function login($payload): array
{
# Android 新
$appkey = 'bca7e84c2d947ac6';
$appsecret = '60698ba2f68e01ce44738920a0ffe768';
$app_key = base64_decode(getDevice('bili_a.app_key_n'));
$app_secret = base64_decode(getDevice('bili_a.secret_key_n'));
$default = [
'access_key' => getAccessToken(),
'actionKey' => 'appkey',
'appkey' => $appkey,
'build' => 6360400,
'channel' => 'bili',
'device' => 'phone',
'mobi_app' => 'android',
'platform' => 'android',
'appkey' => $app_key,
'build' => getDevice('bili_a.build'),
'channel' => getDevice('bili_a.channel'),
'device' => getDevice('bili_a.device'),
'mobi_app' => getDevice('bili_a.mobi_app'),
'platform' => getDevice('bili_a.platform'),
'ts' => time(),
];
$payload = array_merge($payload, $default);
return self::encryption($payload, $appsecret);
return self::encryption($payload, $app_secret);
}
/**
@ -73,25 +45,22 @@ class Sign
*/
public static function common($payload): array
{
# iOS 6680
// $appkey = '27eb53fc9058f8c3';
// $appsecret = 'c2ed53a74eeefe3cf99fbd01d8c9c375';
# Android 旧
$appkey = '1d8b6e7d45233436';
$appsecret = '560c52ccd288fed045859ed18bffd973';
$app_key = base64_decode(getDevice('bili_a.app_key'));
$app_secret = base64_decode(getDevice('bili_a.secret_key'));
$default = [
'access_key' => getAccessToken(),
'actionKey' => 'appkey',
'appkey' => $appkey,
'build' => 6360400,
'device' => 'phone',
'mobi_app' => 'android',
'platform' => 'android',
'appkey' => $app_key,
'build' => getDevice('bili_a.build'),
'device' => getDevice('bili_a.device'),
'mobi_app' => getDevice('bili_a.mobi_app'),
'platform' => getDevice('bili_a.platform'),
'ts' => time(),
];
$payload = array_merge($payload, $default);
return self::encryption($payload, $appsecret);
return self::encryption($payload, $app_secret);
}

View File

@ -18,7 +18,7 @@ class Silver
{
use TimeLock;
protected static $task = [];
protected static array $task = [];
public static function run()
{

View File

@ -82,13 +82,13 @@ class Silver2Coin
// {"code":0,"data":{"coin":1,"gold":1234,"silver":4321,"tid":"Silver2Coin21062316490299678123456"},"message":"兑换成功"}
switch ($data['code']) {
case 0:
Log::notice("[{$type}] 银瓜子兑换硬币: {$data['message']}");
Log::notice("[$type] 银瓜子兑换硬币: {$data['message']}");
return true;
case 403:
Log::warning("[{$type}] 银瓜子兑换硬币: {$data['message']}");
Log::warning("[$type] 银瓜子兑换硬币: {$data['message']}");
return true;
default:
Log::warning("[{$type}] 银瓜子兑换硬币: CODE -> {$data['code']} MSG -> {$data['message']} ");
Log::warning("[$type] 银瓜子兑换硬币: CODE -> {$data['code']} MSG -> {$data['message']} ");
return false;
}
}

View File

@ -18,11 +18,11 @@ class SmallHeart
use TimeLock;
use XliveHeartBeat;
private static $fans_medals = []; // 全部勋章
private static $metal_lock = 0; // 勋章时间锁
private static $interval = 60; // 每次跳动时间
private static $total_time = 0;
private static $metal = null;
private static array $fans_medals = []; // 全部勋章
private static int $metal_lock = 0; // 勋章时间锁
private static int $interval = 60; // 每次跳动时间
private static int $total_time = 0;
private static array|null $metal = null;
public static function run()
{

View File

@ -18,10 +18,10 @@ class Statistics
{
use TimeLock;
private static $push_list = [];
private static $join_list = [];
private static $success_list = [];
private static $profit_list = [];
private static array $push_list = [];
private static array $join_list = [];
private static array $success_list = [];
private static array $profit_list = [];
// Todo 统计开关 统计时间间隔 统计类型
public static function run()
@ -111,6 +111,7 @@ class Statistics
return $c . $v . '前';
}
}
return '';
}
/**
@ -121,7 +122,7 @@ class Statistics
* @param null $second_key
* @return bool
*/
private static function initKeyValue(array &$target, string $key, $value = 0, $second_key = null): bool
private static function initKeyValue(array &$target, string $key, int $value = 0, $second_key = null): bool
{
if (!array_key_exists(self::getTodayKey(), $target)) {
$target[self::getTodayKey()] = [];
@ -142,7 +143,7 @@ class Statistics
* @param null $second_key
* @return mixed
*/
private static function getResult(array &$target, string $key, $second_key = null)
private static function getResult(array &$target, string $key, $second_key = null): mixed
{
is_null($second_key) ? self::initKeyValue($target, $key) : self::initKeyValue($target, $key, 0, $second_key);
return is_null($second_key) ? $target[self::getTodayKey()][$key] : $target[self::getTodayKey()][$key][$second_key];
@ -152,10 +153,10 @@ class Statistics
* @use 获取所有结果
* @param array $target
* @param string $key
* @param string $second_key
* @param string|null $second_key
* @return int
*/
private static function getResults(array &$target, string $key, $second_key = null): int
private static function getResults(array &$target, string $key, string $second_key = null): int
{
$results = 0;
is_null($second_key) ? self::initKeyValue($target, $key) : self::initKeyValue($target, $key, 0, $second_key);
@ -176,7 +177,7 @@ class Statistics
* @param null $second_key
* @return bool
*/
private static function valIncrease(array &$target, string $key, $num = 1, $second_key = null): bool
private static function valIncrease(array &$target, string $key, int $num = 1, $second_key = null): bool
{
is_null($second_key) ? $target[self::getTodayKey()][$key] += $num : $target[self::getTodayKey()][$key][$second_key] += $num;
return true;
@ -190,7 +191,7 @@ class Statistics
* @param string $second_key
* @return bool
*/
private static function valReplace(array &$target, string $key, $data = null, $second_key = ''): bool
private static function valReplace(array &$target, string $key, $data = null, string $second_key = ''): bool
{
is_null($second_key) ? $target[self::getTodayKey()][$key] = $data : $target[self::getTodayKey()][$key][$second_key] = $data;
return true;

View File

@ -19,12 +19,12 @@ class StormRaffle extends BaseRaffle
const ACTIVE_TITLE = '节奏风暴';
const ACTIVE_SWITCH = 'live_storm';
protected static $wait_list = [];
protected static $finish_list = [];
protected static $all_list = [];
protected static array $wait_list = [];
protected static array $finish_list = [];
protected static array $all_list = [];
private static $drop_rate = null;
private static $attempt = null;
private static string|null $drop_rate = null;
private static array|null $attempt = null;
/**
* @use 解析数据
@ -76,7 +76,7 @@ class StormRaffle extends BaseRaffle
*/
private static function formatInfo($id, $num, $info): string
{
return "节奏风暴 {$id} 请求 {$num} 状态 {$info}";
return "节奏风暴 $id 请求 $num 状态 $info";
}
/**
@ -102,7 +102,7 @@ class StormRaffle extends BaseRaffle
];
for ($i = 1; $i < $num; $i++) {
$raw = Curl::post('app', $url, Sign::common($payload));
if (strpos((string)$raw, 'html') !== false) {
if (str_contains((string)$raw, 'html')) {
Log::notice(self::formatInfo($raffle['raffle_id'], $num, '触发哔哩哔哩安全风控策略(412)'));
break;
}
@ -144,7 +144,6 @@ class StormRaffle extends BaseRaffle
continue;
}
Log::notice(self::formatInfo($raffle['raffle_id'], $num, $de_raw['msg']));
continue;
}
}
return [];
@ -153,14 +152,15 @@ class StormRaffle extends BaseRaffle
/**
* @use 解析抽奖信息
* @param array $results
* @return void
* @return mixed
*/
protected static function parseLottery(array $results)
protected static function parseLottery(array $results):mixed
{
foreach ($results as $result) {
$data = $result['source'];
$content = $result['content'];
echo '';
}
return '';
}
}

View File

@ -13,6 +13,7 @@ namespace BiliHelper\Plugin;
use BiliHelper\Core\Curl;
use BiliHelper\Core\Log;
use BiliHelper\Tool\Common;
use JetBrains\PhpStorm\ArrayShape;
class User
{
@ -68,7 +69,7 @@ class User
* @param null $room_id
* @return mixed
*/
public static function webGetUserInfo($room_id = null)
public static function webGetUserInfo($room_id = null): mixed
{
$url = 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByUser';
$payload = [
@ -84,7 +85,7 @@ class User
* @param null $room_id
* @return mixed
*/
public static function appGetUserInfo($room_id = null)
public static function appGetUserInfo($room_id = null): mixed
{
$url = 'https://api.live.bilibili.com/xlive/app-room/v1/index/getInfoByUser';
$payload = [
@ -98,6 +99,7 @@ class User
* @use 转换信息
* @return array
*/
#[ArrayShape(['csrf' => "mixed|string", 'uid' => "mixed|string", 'sid' => "mixed|string"])]
public static function parseCookies(): array
{
$cookies = getCookie();
@ -127,7 +129,7 @@ class User
'ps' => 50,
];
$headers = [
'referer' => "https://space.bilibili.com/{$uid}/fans/follow?tagid=-1",
'referer' => "https://space.bilibili.com/$uid/fans/follow?tagid=-1",
];
$raw = Curl::get('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
@ -165,7 +167,7 @@ class User
'ps' => $page_size,
];
$headers = [
'referer' => "https://space.bilibili.com/{$uid}/fans/follow?tagid={$tag_id}",
'referer' => "https://space.bilibili.com/$uid/fans/follow?tagid=$tag_id",
];
$raw = Curl::get('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
@ -189,7 +191,7 @@ class User
* @param bool $un_follow
* @return bool
*/
public static function setUserFollow(int $follow_uid, $un_follow = false): bool
public static function setUserFollow(int $follow_uid, bool $un_follow): bool
{
$url = 'https://api.live.bilibili.com/relation/v1/Feed/SetUserFollow';
$payload = [
@ -312,7 +314,7 @@ class User
}
Log::debug("获取会员成功 不是年度大会员或已过期");
} else {
Log::debug("获取会员信息失败 {$raw}");
Log::debug("获取会员信息失败 $raw");
}
return false;
}

View File

@ -18,7 +18,7 @@ class VipPrivilege
{
use TimeLock;
private static $privilege = [
private static array $privilege = [
0 => '未知奖励',
1 => 'B币劵',
2 => '会员购优惠券'
@ -66,7 +66,7 @@ class VipPrivilege
if ($de_raw['code'] == 0) {
Log::notice('大会员权益 ' . self::$privilege[$type] . ' 领取成功');
} else {
Log::warning('大会员权益 ' . self::$privilege[$type] . " 领取失败, {$raw}");
Log::warning('大会员权益 ' . self::$privilege[$type] . " 领取失败, $raw");
}
}
@ -89,7 +89,7 @@ class VipPrivilege
Log::info('获取大会员权益列表成功');
return $de_raw['data']['list'];
} else {
Log::warning("获取大会员权益列表失败 {$raw}");
Log::warning("获取大会员权益列表失败 $raw");
return [];
}
}

View File

@ -15,23 +15,25 @@ use BiliHelper\Util\TimeLock;
use Amp\Delayed;
use Exception;
use JetBrains\PhpStorm\Pure;
use Socket\Raw\Factory;
use function get_class;
class ZoneTcpClient
{
use TimeLock;
private static $raffle_id = 0;
private static $raffle_list = [];
private static $server = [];
private static $server_key = null;
private static int $raffle_id = 0;
private static array $raffle_list = [];
private static array $server = [];
private static string|null $server_key = null;
private static $area_id;
private static $room_id;
private static int|string $area_id;
private static int|string $room_id;
private static $client;
private static $client_maps = [];
private static $trigger_restart = [];
private static $socket_timeout = 0;
private static array $client_maps = [];
private static array $trigger_restart = [];
private static int $socket_timeout = 0;
/**
@ -70,7 +72,7 @@ class ZoneTcpClient
{
$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, "status" => false];
self::$client_maps["server$area_id"] = ["area_id" => null, "room_id" => null, "client" => null, "heart_beat" => 0, "status" => false];
self::triggerReConnect([
'area_id' => $area_id,
'wait_time' => time()
@ -85,7 +87,7 @@ class ZoneTcpClient
*/
private static function triggerReConnect(array $area_data, string $reason)
{
Log::debug("Reconnect Reason: {$area_data['area_id']} -> {$reason}");
Log::debug("Reconnect Reason: {$area_data['area_id']} -> $reason");
self::$client_maps["server" . $area_data['area_id']]['status'] = false;
array_push(self::$trigger_restart, $area_data);
}
@ -152,7 +154,7 @@ class ZoneTcpClient
* @param bool $assoc 是否返回对象or关联数组默认返回关联数组
* @return array|bool|object 成功返回转换后的对象或数组,失败返回 false
*/
private static function analyJson($data = '', $assoc = true)
private static function analyJson(string $data = '', bool $assoc = true): object|bool|array
{
if (is_array($data)) {
return $data;
@ -178,14 +180,14 @@ class ZoneTcpClient
// Log::info("当前直播间现有 {$num} 人聚众搞基!");
return false;
}
$de_raw = self::analyJson($msg, true);
$de_raw = self::analyJson($msg);
// 进入房间返回
if (isset($de_raw['code']) && !$de_raw['code']) {
return false;
}
// 部分cmd抽风
if (!$de_raw || !isset($de_raw['cmd'])) {
Log::warning("解析错误: {$msg}");
Log::warning("解析错误: $msg");
return false;
}
$data = [];
@ -301,7 +303,7 @@ class ZoneTcpClient
];
// echo self::$room_id . '--' . $real_room_id . PHP_EOL;
}
if ($msg_type == 6 && strpos($msg_common, '节奏风暴') !== false) {
if ($msg_type == 6 && str_contains($msg_common, '节奏风暴')) {
$data = [
'room_id' => $real_room_id,
'raffle_id' => self::$raffle_id++,
@ -397,6 +399,7 @@ class ZoneTcpClient
* @use 心跳包
* @return string
*/
#[Pure]
private static function genHeartBeatPkg(): string
{
return self::packMsg('', 0x0002);
@ -437,12 +440,12 @@ class ZoneTcpClient
* @param $value
* @return array|false
*/
private static function unPackMsg($value)
private static function unPackMsg($value): bool|array
{
if (strlen($value) < 4) {
Log::warning("unPackMsg: 包头异常 " . strlen($value));
return [];
};
}
// Log::info(json_encode($head, true));
return unpack('Npacklen/nheadlen/nver/Nop/Nseq', $value);
}
@ -472,9 +475,9 @@ class ZoneTcpClient
* @use 读数据
* @param $length
* @param bool $is_header
* @return array|bool
* @return bool|array|string
*/
private static function reader($length, bool $is_header = false)
private static function reader($length, bool $is_header = false): bool|array|string
{
$data = false;
try {
@ -483,8 +486,8 @@ class ZoneTcpClient
$socket = self::$client->getResource();
while ($length) {
if ($length < 1 || $length > 65535) {
Log::warning("Socket error: [{$ret}] [{$length}]" . PHP_EOL);
throw new Exception("Socket error: [{$ret}] [{$length}]");
Log::warning("Socket error: [$ret] [$length]" . PHP_EOL);
throw new Exception("Socket error: [$ret] [$length]");
}
$cnt = 0;
$w = NULL;
@ -502,8 +505,8 @@ class ZoneTcpClient
// Todo unable to read from socket[104]: Connection reset by peer
$ret = socket_recv($socket, $buffer, $length, 0);
if ($ret < 1) {
Log::warning("Socket error: [{$ret}] [{$length}]" . PHP_EOL);
throw new Exception("Socket error: [{$ret}] [{$length}]");
Log::warning("Socket error: [$ret] [$length]" . PHP_EOL);
throw new Exception("Socket error: [$ret] [$length]");
}
$data .= $buffer;
unset($buffer);
@ -564,7 +567,7 @@ class ZoneTcpClient
$length = $head['packlen'] ?? 16;
$type = $head['op'] ?? 0x0000;
$len_body = $length - 16;
Log::debug("(AreaId={$client_info['area_id']} -> RoomId={$client_info['room_id']} -> Len={$len_body})");
Log::debug("(AreaId={$client_info['area_id']} -> RoomId={$client_info['room_id']} -> Len=$len_body)");
if (!$len_body)
continue;
$body = self::reader($len_body);
@ -595,9 +598,9 @@ class ZoneTcpClient
$total = strlen($data);
while (true) {
if ($step > 165535) {
Log::warning("v2_split: 数据step异常 {$step}");
Log::warning("v2_split: 数据step异常 $step");
break;
};
}
if ($step == $total) break;
$bin = substr($data, $step, 16);
$head = self::unPackMsg($bin);
@ -615,8 +618,8 @@ class ZoneTcpClient
*/
private static function getClass($object): string
{
$class = \get_class($object);
return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class) . '@anonymous' : $class;
$class = get_class($object);
return 'c' === $class[0] && str_starts_with($class, "class@anonymous\0") ? get_parent_class($class) . '@anonymous' : $class;
}
/**

View File

@ -26,10 +26,10 @@ class BaseTask
* @param null $default
* @return mixed
*/
public static function choice(array $options, $default = null)
public static function choice(array $options, $default = null): mixed
{
$option = static::interactor()->choice('Select', $options, $default, true);
static::interactor()->greenBold("You selected: {$options[$option]}", true);
static::interactor()->greenBold("You selected: $options[$option]", true);
// return $options[$option];
return $option;
}

View File

@ -10,13 +10,13 @@
namespace BiliHelper\Script;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
class DelDynamic extends BaseTask
{
public static $description = '批量删除动态默认单次最大清理300个动态.';
public static string $description = '批量删除动态默认单次最大清理300个动态.';
public static function run(){
public static function run()
{
Log::error('当前功能未完成');
}
}

View File

@ -14,7 +14,7 @@ use BiliHelper\Core\Curl;
class UnFollow extends BaseTask
{
public static $description = '批量清理选定分组关注默认单次最大清理600个关注.';
public static string $description = '批量清理选定分组关注默认单次最大清理600个关注.';
/**
* @throws \Exception
@ -59,9 +59,9 @@ class UnFollow extends BaseTask
// {"code":0,"message":"0","ttl":1}
$data = json_decode($raw, true);
if ($data['code'] == 0) {
Log::notice("UP.{$up_uid} - {$up_uname} 取关成功");
Log::notice("UP.$up_uid - $up_uname 取关成功");
} else {
Log::error("UP.{$up_uid} - {$up_uname} 取关失败 CODE -> {$data['code']} MSG -> {$data['message']} ");
Log::error("UP.$up_uid - $up_uname 取关失败 CODE -> {$data['code']} MSG -> {$data['message']} ");
break;
}
sleep(random_int(5, 10));
@ -99,7 +99,7 @@ class UnFollow extends BaseTask
$following[$up['mid']] = $up['uname'];
}
// 打印和延迟
Log::info("已获取分组 {$tag_id} 页码 {$pn}");
Log::info("已获取分组 $tag_id 页码 $pn");
sleep(random_int(4, 8));
// 如果页面不等于 max_ps 跳出
if (count($data['data']) != $max_ps) {
@ -111,7 +111,7 @@ class UnFollow extends BaseTask
}
}
$following_num = count($following);
Log::notice("已获取分组 {$tag_id} 有效关注数 {$following_num}");
Log::notice("已获取分组 $tag_id 有效关注数 $following_num");
return $following;
}
@ -120,7 +120,7 @@ class UnFollow extends BaseTask
* @use 获取分组
* @return mixed
*/
private static function relationTags()
private static function relationTags(): mixed
{
$url = 'https://api.bilibili.com/x/relation/tags';
$payload = [];
@ -135,7 +135,7 @@ class UnFollow extends BaseTask
$options[$tag['tagid']] = "分组:{$tag['name']} - 关注数:{$tag['count']}";
}
$option = self::choice($options);
Log::notice("已获取分组 {$option} - {$options[$option]}");
Log::notice("已获取分组 $option - $options[$option]");
return $option;
} else {
Log::error("获取关注分组失败 CODE -> {$data['code']} MSG -> {$data['message']} ");

View File

@ -41,7 +41,7 @@ class User
* @use 用户
* @return mixed
*/
public static function userInfo()
public static function userInfo(): mixed
{
$url = 'https://api.bilibili.com/x/web-interface/nav';
$payload = [];

View File

@ -11,14 +11,12 @@
namespace BiliHelper\Tool;
use BiliHelper\Core\Log;
class BvToAv
{
protected $tr = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF";
protected $xor = 177451812;
protected $add = 8728348608;
protected $s = [11, 10, 3, 8, 4, 6];
protected string $tr = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF";
protected int $xor = 177451812;
protected int $add = 8728348608;
protected array $s = [11, 10, 3, 8, 4, 6];
/**
@ -26,7 +24,7 @@ class BvToAv
* @param $bv
* @return int|string
*/
public function dec($bv)
public function dec($bv): int|string
{
$r = 0;
$tr = array_flip(str_split($this->tr));

View File

@ -1,60 +0,0 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
* Source: https://github.com/fzaninotto/Faker/
*/
namespace BiliHelper\Tool;
use Flintstone\Flintstone;
use Flintstone\Formatter\JsonFormatter;
class Cache
{
private static $instance;
private static function getInstance()
{
if (is_null(self::$instance)) {
self::configureInstance();
}
return self::$instance;
}
private static function configureInstance()
{
self::$instance = new Flintstone(
'BHP', [
'dir' => APP_CACHE_PATH,
// 'gzip' => true,
'formatter' => new JsonFormatter()
]);
// self::$instance->set('bob', ['email' => 'bob@site.com', 'password' => '123456']);
}
public static function get()
{
// Get a key
// $user = $users->get('bob');
// echo 'Bob, your email is ' . $user['email'];
$args = func_get_args();
return self::getInstance()->get(...$args);
}
public static function set()
{
// Set a key
// $users->set('bob', ['email' => 'bob@site.com', 'password' => '123456']);
$args = func_get_args();
self::getInstance()->set(...$args);
}
}

View File

@ -48,7 +48,7 @@ class Common
* @param string $charset
* @return string
*/
public static function replaceStar($str, $start, $end = 0, $dot = "*", $charset = "UTF-8"): string
public static function replaceStar($str, $start, int $end = 0, string $dot = "*", string $charset = "UTF-8"): string
{
$len = mb_strlen($str, $charset);
if ($start == 0 || $start > $len) {

View File

@ -20,6 +20,6 @@ class DumpMemory
$unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
$size = memory_get_usage(true);
$memory = @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i];
Log::warning("{$title} # 内存 # {$memory}");
Log::warning("$title # 内存 # $memory");
}
}

View File

@ -22,7 +22,7 @@ class Faker
* @example 79907610
*
*/
public static function numberBetween($int1 = 0, $int2 = 2147483647): int
public static function numberBetween(int $int1 = 0, int $int2 = 2147483647): int
{
$min = $int1 < $int2 ? $int1 : $int2;
$max = $int1 < $int2 ? $int2 : $int1;
@ -36,7 +36,7 @@ class Faker
* @param int $except
* @return int
*/
public static function randomDigitNot($except): int
public static function randomDigitNot(int $except): int
{
$result = self::numberBetween(0, 8);
if ($result >= $except) {
@ -53,7 +53,7 @@ class Faker
* @param string $string String that needs to bet parsed
* @return string
*/
public static function asciify($string = '****'): string
public static function asciify(string $string = '****'): string
{
return preg_replace_callback('/\*/u', 'static::randomAscii', $string);
}
@ -73,7 +73,7 @@ class Faker
/**
* @example '237.149.115.38'
*/
public function ipv4()
public function ipv4(): bool|string
{
return long2ip(mt_rand(0, 1) == 0 ? mt_rand(-2147483648, -2) : mt_rand(16777216, 2147483647));
}
@ -94,7 +94,7 @@ class Faker
/**
* @example '10.1.1.17'
*/
public static function localIpv4()
public static function localIpv4(): bool|string
{
if (static::numberBetween(0, 1) === 0) {
// 10.x.x.x range
@ -113,17 +113,15 @@ class Faker
for ($i = 0; $i < 6; $i++) {
$mac[] = sprintf('%02X', static::numberBetween(0, 0xff));
}
$mac = implode(':', $mac);
return $mac;
return implode(':', $mac);
}
/**
* @use 转Ascii
* @param $string
* @return array|string|string[]
* @return array|string
*/
protected static function toAscii($string)
protected static function toAscii($string): array|string
{
static $arrayFrom, $arrayTo;

View File

@ -11,6 +11,8 @@
namespace BiliHelper\Tool;
use JetBrains\PhpStorm\Pure;
class File
{
@ -131,9 +133,10 @@ class File
/**
* @use 获取文件详细信息
* @param string $filename
* @return array|false
* @return array|bool
*/
public static function getInfo(string $filename): bool
#[Pure]
public static function getInfo(string $filename): array|bool
{
// 如果不是文件 或者 不可读返回false
if (!is_file($filename) || !is_readable($filename)) {
@ -143,7 +146,7 @@ class File
return [
"文件名称" => basename($filename),
"文件类型" => filetype($filename),
"文件大小" => trans_byte(filesize($filename)),
"文件大小" => static::transByte(filesize($filename)),
"创建时间" => date('Y-m-d H:i:s', filectime($filename)),
"修改时间" => date('Y-m-d H:i:s', filemtime($filename)),
"上一次访问时间" => date('Y-m-d H:i:s', fileatime($filename)),
@ -157,7 +160,7 @@ class File
* @param int $precision 小数点保留位数
* @return string 转换后的单位
*/
public static function transByte(int $byte, $precision = 2): string
public static function transByte(int $byte, int $precision = 2): string
{
$kb = 1024;
$mb = 1024 * $kb;
@ -180,6 +183,7 @@ class File
if ($byte < $tb) {
return round($byte / $tb, $precision) . ' GB';
}
return '';
}
@ -188,7 +192,7 @@ class File
* @param string $filename
* @return false|string
*/
public static function readString(string $filename)
public static function readString(string $filename): bool|string
{
if (is_file($filename) && is_readable($filename)) {
return file_get_contents($filename);
@ -203,7 +207,7 @@ class File
* @param bool $skip_empty_lines
* @return array|false
*/
public static function readArray(string $filename, bool $skip_empty_lines = false)
public static function readArray(string $filename, bool $skip_empty_lines = false): bool|array
{
if (is_file($filename) && is_readable($filename)) {
if ($skip_empty_lines) {
@ -214,6 +218,7 @@ class File
return file($filename);
}
}
return false;
}
@ -224,8 +229,9 @@ class File
* @param boolean $clear_content 是否清空原始内容再写入
* @return bool true|false
*/
public static function write(string $filename, $data, bool $clear_content = false)
public static function write(string $filename, mixed $data, bool $clear_content = false): bool
{
$srcData = '';
$dirname = dirname($filename);
// 检测目标路径是否存在
if (!file_exists($dirname)) {

View File

@ -27,12 +27,11 @@ class Generator
$chars = md5(uniqid(mt_rand(), true));
$chars = substr_replace($chars, "4", 12, 1);
$chars = substr_replace($chars, "a", 16, 1);
$uuid = substr($chars, 0, 8) . '-'
return substr($chars, 0, 8) . '-'
. substr($chars, 8, 4) . '-'
. substr($chars, 12, 4) . '-'
. substr($chars, 16, 4) . '-'
. substr($chars, 20, 12);
return $uuid;
}
/**
@ -54,11 +53,15 @@ class Generator
*/
public static function buvid(): string
{
// XW UUID
// XX AndroidID
// XY MAC
// XZ IMEI
// XYD5B85DA7212341F51C612344A6B8C6C21234
$mac = Faker::macAddress();
$md5 = md5($mac);
$md5_arr = str_split($md5);
return strtoupper("XY{$md5_arr[2]}{$md5_arr[12]}{$md5_arr[22]}{$md5}");
return strtoupper("XY$md5_arr[2]$md5_arr[12]$md5_arr[22]$md5");
}
/**

View File

@ -12,6 +12,8 @@
namespace BiliHelper\Tool;
use Exception;
/** **********************************************************************************
* Generate hundreds of thousands of unique mobile & desktop User Agents that are 100% authentic.
* Supports Hundreds of Android devices, 32 & 64 bit versions of Windows XP-10.5, Linux 540-686, and Mac 7-10.12
@ -23,7 +25,7 @@ class UserAgent
* Windows Operating System list with dynamic versioning
* @var array $windows_os
*/
public $windows_os = [
public array $windows_os = [
'[Windows; |Windows; U; |]Windows NT 6.:number0-3:;[ Win64; x64| WOW64| x64|]',
'[Windows; |Windows; U; |]Windows NT 10.:number0-5:;[ Win64; x64| WOW64| x64|]'
];
@ -31,7 +33,7 @@ class UserAgent
* Linux Operating Systems [limited]
* @var array $linux_os
*/
public $linux_os = [
public array $linux_os = [
'[Linux; |][U; |]Linux x86_64',
'[Linux; |][U; |]Linux i:number5-6::number4-8::number0-6: [x86_64|]'
];
@ -39,7 +41,7 @@ class UserAgent
* Mac Operating System (OS X) with dynamic versioning
* @var array $mac_os
*/
public $mac_os = [
public array $mac_os = [
'Macintosh; [U; |]Intel Mac OS X :number7-9:_:number0-9:_:number0-9:',
'Macintosh; [U; |]Intel Mac OS X 10_:number0-12:_:number0-9:'
];
@ -47,7 +49,7 @@ class UserAgent
* Versions of Android to be used
* @var array $androidVersions
*/
public $androidVersions = [
public array $androidVersions = [
'4.3.1',
'4.4',
'4.4.1',
@ -67,12 +69,12 @@ class UserAgent
* Holds the version of android for the User Agent being generated
* @property string $androidVersion
*/
public $androidVersion;
public string $androidVersion;
/**
* Android devices and for specific android versions
* @var array $androidDevices
*/
public $androidDevices = [
public array $androidDevices = [
'4.3' => [
'GT-I9:number2-5:00 Build/JDQ39',
'Nokia 3:number1-3:[10|15] Build/IMM76D',
@ -165,12 +167,12 @@ class UserAgent
'LG-H:number90-93:0 Build/NRD90[C|M]'
]
];
public $locale = 'en-US';
public string $locale = 'en-US';
/**
* List of "OS" strings used for android
* @var array $android_os
*/
public $android_os = [
public array $android_os = [
'Linux; Android :androidVersion:; :androidDevice:',
//Todo: Add a $windowsDevices variable that does the same as androidDevice
//'Windows Phone 10.0; Android :androidVersion:; :windowsDevice:',
@ -181,7 +183,7 @@ class UserAgent
* List of "OS" strings used for iOS
* @var array $mobile_ios
*/
public $mobile_ios = [
public array $mobile_ios = [
'iphone' => 'iPhone; CPU iPhone OS :number7-11:_:number0-9:_:number0-9:; like Mac OS X;',
'ipad' => 'iPad; CPU iPad OS :number7-11:_:number0-9:_:number0-9: like Mac OS X;',
'ipod' => 'iPod; CPU iPod OS :number7-11:_:number0-9:_:number0-9:; like Mac OS X;'
@ -190,9 +192,10 @@ class UserAgent
/**
* Get a random operating system
* @param string|null $os
* @return string *
* @return array|string|null *
* @throws \Exception
*/
public function getOS(string $os = NULL)
public function getOS(string $os = NULL): array|string|null
{
$_os = [];
if ($os === NULL || in_array($os, ['chrome', 'firefox', 'explorer'])) {
@ -204,12 +207,12 @@ class UserAgent
$selected_os = rtrim($_os[random_int(0, count($_os) - 1)], ';');
// check for spin syntax
if (strpos($selected_os, '[') !== FALSE) {
if (str_contains($selected_os, '[')) {
$selected_os = self::processSpinSyntax($selected_os);
}
// check for random number syntax
if (strpos($selected_os, ':number') !== FALSE) {
if (str_contains($selected_os, ':number')) {
$selected_os = self::processRandomNumbers($selected_os);
}
@ -222,9 +225,10 @@ class UserAgent
/**
* Get Mobile OS
* @param string|null $os Can specifiy android, iphone, ipad, ipod, or null/blank for random
* @return string *
* @return array|string|null *
* @throws \Exception
*/
public function getMobileOS(string $os = NULL)
public function getMobileOS(string $os = NULL): array|string|null
{
$os = strtolower($os);
$_os = [];
@ -242,13 +246,13 @@ class UserAgent
}
// select random mobile os
$selected_os = rtrim($_os[random_int(0, count($_os) - 1)], ';');
if (strpos($selected_os, ':androidVersion:') !== FALSE) {
if (str_contains($selected_os, ':androidVersion:')) {
$selected_os = $this->processAndroidVersion($selected_os);
}
if (strpos($selected_os, ':androidDevice:') !== FALSE) {
if (str_contains($selected_os, ':androidDevice:')) {
$selected_os = $this->addAndroidDevice($selected_os);
}
if (strpos($selected_os, ':number') !== FALSE) {
if (str_contains($selected_os, ':number')) {
$selected_os = self::processRandomNumbers($selected_os);
}
return $selected_os;
@ -258,8 +262,9 @@ class UserAgent
* static::processRandomNumbers
* @param $selected_os
* @return null|string|string[] *
* @throws \Exception
*/
public static function processRandomNumbers($selected_os)
public static function processRandomNumbers($selected_os): array|string|null
{
return preg_replace_callback('/:number(\d+)-(\d+):/i', function ($matches) {
return random_int($matches[1], $matches[2]);
@ -271,7 +276,7 @@ class UserAgent
* @param $selected_os
* @return null|string|string[] *
*/
public static function processSpinSyntax($selected_os)
public static function processSpinSyntax($selected_os): array|string|null
{
return preg_replace_callback('/\[([\w\-\s|;]*?)\]/i', function ($matches) {
$shuffle = explode('|', $matches[1]);
@ -284,7 +289,7 @@ class UserAgent
* @param $selected_os
* @return null|string|string[] *
*/
public function processAndroidVersion($selected_os)
public function processAndroidVersion($selected_os): array|string|null
{
$this->androidVersion = $version = $this->androidVersions[array_rand($this->androidVersions)];
return preg_replace_callback('/:androidVersion:/i', function ($matches) use ($version) {
@ -297,7 +302,7 @@ class UserAgent
* @param $selected_os
* @return null|string|string[] *
*/
public function addAndroidDevice($selected_os)
public function addAndroidDevice($selected_os): array|string|null
{
$devices = $this->androidDevices[substr($this->androidVersion, 0, 3)];
$device = $devices[array_rand($devices)];
@ -312,6 +317,7 @@ class UserAgent
* static::chromeVersion
* @param $version
* @return string *
* @throws \Exception
*/
public static function chromeVersion($version): string
{
@ -323,6 +329,7 @@ class UserAgent
* static::firefoxVersion
* @param $version
* @return string *
* @throws \Exception
*/
public static function firefoxVersion($version): string
{
@ -333,6 +340,7 @@ class UserAgent
* static::windows
* @param $version
* @return string *
* @throws \Exception
*/
public static function windows($version): string
{
@ -343,6 +351,7 @@ class UserAgent
* generate
* @param null $userAgent
* @return string *
* @throws \Exception
*/
public function generate($userAgent = NULL, $locale = null): string
{
@ -395,7 +404,7 @@ class UserAgent
. (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603))
. '.' . random_int(0, 9);
} else {
new Exception('Unable to determine user agent to generate');
throw new Exception('Unable to determine user agent to generate');
}
}
}

View File

@ -11,14 +11,15 @@
namespace BiliHelper\Util;
use JsonDecodeStream\Parser;
use stdClass;
trait AllotTasks
{
// protected static $repository = '';
protected static $tasks = [];
protected static $work_status = [
protected static array $tasks = [];
protected static array $work_status = [
'work_updated' => null,
'estimated_time' => null,
'work_completed' => null,
@ -40,7 +41,7 @@ trait AllotTasks
* @param bool $time
* @return bool
*/
protected static function pushTask(string $operation, \stdClass $act, bool $time = false): bool
protected static function pushTask(string $operation, stdClass $act, bool $time = false): bool
{
$task = [
'operation' => $operation,
@ -53,9 +54,9 @@ trait AllotTasks
/**
* @use 拉取任务
* @return false|mixed
* @return mixed
*/
protected static function pullTask()
protected static function pullTask(): mixed
{
// 任务列表为空
if (empty(static::$tasks)) {

View File

@ -25,10 +25,10 @@ abstract class BaseRaffle
const ACTIVE_TITLE = '';
const ACTIVE_SWITCH = '';
protected static $wait_list;
protected static $finish_list;
protected static $all_list;
protected static $banned_rids = [];
protected static array $wait_list;
protected static array $finish_list;
protected static array $all_list;
protected static array $banned_rids = [];
public static function run()
{
@ -129,7 +129,7 @@ abstract class BaseRaffle
* @param array $results
* @return mixed
*/
abstract protected static function parseLottery(array $results);
abstract protected static function parseLottery(array $results): mixed;
/**
* @use 二维数组按key排序
@ -209,7 +209,7 @@ abstract class BaseRaffle
}
$wait_num = count(static::$wait_list);
if ($wait_num > 10 && ($wait_num % 2)) {
Log::info("当前队列中共有 {$wait_num}" . static::ACTIVE_TITLE . "待抽奖");
Log::info("当前队列中共有 $wait_num" . static::ACTIVE_TITLE . "待抽奖");
}
return true;
}

View File

@ -16,9 +16,9 @@ use Sven\FileConfig\Drivers\Json;
trait FilterWords
{
protected static $store;
protected static Store $store;
protected static $store_status;
protected static $repository = APP_DATA_PATH . 'filter_library.json';
protected static string $repository = APP_DATA_PATH . 'filter_library.json';
/**
* @use 加载配置信息

112
src/util/Singleton.php Normal file
View File

@ -0,0 +1,112 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
declare(strict_types=1);
namespace BiliHelper\Util;
use BiliHelper\Exceptions\SingletonException;
/**
* Singleton Trait
*
* @author Alexander Smyslov <smyslov@selby.su>
* @package Smysloff\Traits
*/
trait Singleton
{
/**
* Singleton instance
*/
private static $instance = null;
/**
* Creates an instance of Singleton
* and always returns same instance
*
* @return Singleton
*/
public static function getInstance(): self
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Initializes the singleton
*/
protected function init(): void
{
}
/**
* Singleton constructor.
* Singleton constructor needs to be private
* 不允许从外部调用以防止创建多个实例
* 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
*/
final public function __construct()
{
$this->init();
}
/**
* Singleton can't be cloned
* 防止实例被克隆(这会创建实例的副本)
*/
final public function __clone()
{
throw new SingletonException("Singleton can't be cloned");
}
/**
* Singleton can't be serialized
*/
final public function __sleep()
{
throw new SingletonException("Singleton can't be serialized");
}
/**
* Singleton can't be deserialized
* 防止反序列化(这将创建它的副本)
*/
final public function __wakeup()
{
throw new SingletonException("Singleton can't be deserialized");
}
/**
* 其他方法自动调用
* @param $method
* @param $args
* @return mixed
*/
public function __call($method, $args)
{
return call_user_func_array([static::$instance, $method], $args);
}
/**
* 静态调用
* @param $method
* @param $args
* @return mixed
*/
public static function __callStatic($method, $args)
{
return call_user_func_array([static::$instance, $method], $args);
}
}

View File

@ -13,11 +13,12 @@ namespace BiliHelper\Util;
use Amp\Delayed;
use BiliHelper\Core\Task;
use BiliHelper\Plugin\Schedule;
use ReflectionClass;
trait TimeLock
{
public static $lock = 0;
public static $pause_status = false;
public static int $lock = 0;
public static bool $pause_status = false;
/**
* @use 设置时间
@ -26,7 +27,7 @@ trait TimeLock
public static function setLock(int $lock)
{
if (!static::getpauseStatus()) {
Task::getInstance()::_setLock(static::getBaseClass(), time() + $lock);
Task::getInstance()->_setLock(static::getBaseClass(), time() + $lock);
}
}
@ -36,7 +37,7 @@ trait TimeLock
*/
public static function getLock(): int
{
return Task::getInstance()::_getLock(static::getBaseClass());
return Task::getInstance()->_getLock(static::getBaseClass());
}
/**
@ -106,7 +107,7 @@ trait TimeLock
// substr(strrchr($class, "\\"), 1);
// substr($class, strrpos($class, '\\') + 1);
// array_pop(explode('\\', $class));
Schedule::triggerRefused((new \ReflectionClass(static::class))->getShortName());
Schedule::triggerRefused((new ReflectionClass(static::class))->getShortName());
}
/**

View File

@ -14,26 +14,27 @@ use BiliHelper\Core\Curl;
use BiliHelper\Core\Log;
use BiliHelper\Plugin\Live;
use BiliHelper\Tool\Generator;
use JetBrains\PhpStorm\ArrayShape;
trait XliveHeartBeat
{
protected static $_data = ['id' => []]; // data [ets, benchmark, time, secret_rule, id] data->id [parent_area_id, area_id, 0, room_id]
protected static $_secret_rule = []; // secret_rule [2, 3, 1, 5]
protected static $_room_info = []; // 心跳房间信息
protected static array|null $_data = ['id' => []]; // data [ets, benchmark, time, secret_rule, id] data->id [parent_area_id, area_id, 0, room_id]
protected static array $_secret_rule = []; // secret_rule [2, 3, 1, 5]
protected static array $_room_info = []; // 心跳房间信息
protected static $_retry = 3; // 重试次数
protected static $_count_num = 0; // 计数
protected static $_count_time = 0; // 计时间
protected static int $_retry = 3; // 重试次数
protected static int $_count_num = 0; // 计数
protected static int $_count_time = 0; // 计时间
protected static $_current_room_id = 0; // 当前运行的ROOM_ID
protected static $_enc_server = null; // 加密服务器 依赖配置文件
protected static int $_current_room_id = 0; // 当前运行的ROOM_ID
protected static string|null $_enc_server = null; // 加密服务器 依赖配置文件
protected static $_default = 0; // 默认值
protected static int $_default = 0; // 默认值
// 请求配置
protected static $_user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36';
protected static $_headers = [
protected static string $_user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36';
protected static array $_headers = [
'content-type' => 'application/x-www-form-urlencoded',
'origin' => 'https://live.bilibili.com',
'referer' => 'https://live.bilibili.com/',
@ -45,9 +46,9 @@ trait XliveHeartBeat
* @param int $room_id
* @param int $max_time
* @param int $max_num
* @return int|mixed
* @return mixed
*/
protected static function xliveHeartBeatTask(int $room_id, int $max_time, int $max_num)
protected static function xliveHeartBeatTask(int $room_id, int $max_time, int $max_num): mixed
{
// 加载依赖
if (!static::depend()) {
@ -150,7 +151,7 @@ trait XliveHeartBeat
/**
* @use E心跳
* @param array $id
* @return array|false[]
* @return array
*/
protected static function eHeartBeat(array $id): array
{
@ -180,7 +181,7 @@ trait XliveHeartBeat
/**
* @use X心跳
* @param array $id
* @return array|bool[]
* @return array
*/
protected static function xHeartBeat(array $id): array
{
@ -212,7 +213,7 @@ trait XliveHeartBeat
* @param array $r
* @return string|false
*/
protected static function encParamS(array $t, array $r)
protected static function encParamS(array $t, array $r): bool|string
{
$headers = [
'Content-Type' => 'application/json',
@ -242,6 +243,7 @@ trait XliveHeartBeat
* @param array $t
* @return array
*/
#[ArrayShape(['id' => "mixed", 'device' => "mixed", 'ets' => "mixed", 'benchmark' => "mixed", 'time' => "mixed", 'ts' => "mixed", 'ua' => "mixed"])]
protected static function formatT(array $t): array
{
// print_r($t);

View File

@ -0,0 +1,3 @@
# Ignore everything in this directory
*
# Except this file !.gitkeep

View File

@ -11,10 +11,10 @@
class ConfigGenerator
{
public $filename;
public $template;
private $options = ['APP_USER', 'APP_PASS'];
private $default_filename = 'user.ini.example';
public string $filename;
public string $template;
private array $options = ['APP_USER', 'APP_PASS'];
private string $default_filename = 'user.ini.example';
/**
* ConfigGenerator constructor.
@ -30,7 +30,7 @@ class ConfigGenerator
* @param string $content
* @return string|string[]|null
*/
private function envReplace(string $key, string $value, string $content)
private function envReplace(string $key, string $value, string $content): array|string|null
{
return preg_replace(
'/^' . $key . '=.*' . '/m',
@ -44,7 +44,7 @@ class ConfigGenerator
* @param int $max_char
* @return string
*/
private function cliInput(string $msg, $max_char = 100): string
private function cliInput(string $msg, int $max_char = 100): string
{
$stdin = fopen('php://stdin', 'r');
echo '# ' . $msg;
@ -61,7 +61,7 @@ class ConfigGenerator
$this->filename = $this->cliInput('请输入配置文件名: ');
$this->template = file_get_contents($this->default_filename);
foreach ($this->options as $index => $option) {
$value = $this->cliInput("请输入{$option}: ");
$value = $this->cliInput("请输入$option: ");
$this->template = $this->envReplace($option, $value, $this->template);
}
file_put_contents(__DIR__ . "\\$this->filename.ini", $this->template);