.\.editorconfig

This commit is contained in:
Lkeme 2025-09-04 13:01:55 +08:00
parent cc74188f44
commit 374591393e
8 changed files with 291 additions and 146 deletions

View File

@ -29,7 +29,7 @@
<p align=center>
<img src="https://img.shields.io/badge/Version-2.5.0.250823-orange.svg?longCache=true&style=for-the-badge" alt="">
<img src="https://img.shields.io/badge/Version-2.5.1.250904-orange.svg?longCache=true&style=for-the-badge" alt="">
<img src="https://img.shields.io/badge/PHP-8.1+-green.svg?longCache=true&style=for-the-badge" alt="">
<img src="https://img.shields.io/badge/Composer-latest-blueviolet.svg?longCache=true&style=for-the-badge" alt="">
<img src="https://img.shields.io/badge/License-mit-blue.svg?longCache=true&style=for-the-badge" alt="">

View File

@ -8,6 +8,25 @@
[comment]: <> (</details>)
## v2.5.1.250904 alpha (2025-09-04)
### Added
-
### Changed
- 更新设备信息
- 更新部分使用文档
### Fixed
- 尝试修复年度大会员领取权益**特色权益二选一**
### Remarks
-
## v2.5.0.250823 alpha (2025-08-23)
### Added

View File

@ -45,7 +45,7 @@
+ 阿里云(全量镜像)
```shell script
```shell
# 使用帮助
> https://developer.aliyun.com/composer
# 使用命令
@ -54,7 +54,7 @@
+ 恢复默认镜像|Composer.phar加速下载
```shell script
```shell
> composer config -g --unset repos.packagist
> https://mirrors.cloud.tencent.com/composer/composer.phar
@ -67,7 +67,7 @@
+ cnpkg(全量镜像)
```shell script
```shell
# 使用帮助
> https://php.cnpkg.org/
# 使用命令
@ -76,7 +76,7 @@
+ 腾讯云(全量镜像)
```shell script
```shell
# 使用帮助
> https://mirrors.cloud.tencent.com/help/composer.html
# 使用命令
@ -85,7 +85,7 @@
+ PhpComposer(全量镜像)
```shell script
```shell
# 使用帮助
> https://pkg.phpcomposer.com/
# 使用命令
@ -94,7 +94,7 @@
+ 华为云(全量镜像)
```shell script
```shell
# 使用帮助
> https://mirrors.huaweicloud.com/repository/php/
# 使用命令
@ -103,7 +103,7 @@
+ 交通大学(非全量镜像)
```shell script
```shell
# 使用帮助
> https://packagist.mirrors.sjtug.sjtu.edu.cn/
# 使用命令
@ -118,31 +118,27 @@
1. 下载(克隆)项目代码,初始化项目
```shell script
```shell
$ git clone https://github.com/lkeme/BiliHelper-personal.git
$ cp -r profile/example profile/user
```
2. 使用 [composer](https://getcomposer.org/download/) 工具进行安装
```shell script
```shell
$ composer install
```
[comment]: <> (composer dump-autoload &#40;-o&#41;)
[comment]: <> (composer dumpautoload &#40;-o&#41;)
3. 按照说明修改配置文件 `profile/user/config/user.ini`
```shell script
```shell
# 默认只需填写帐号密码,按需求开启其他功能即可
...
```
4. 运行测试
```shell script
```shell
$ php app.php
# 默认配置user
$ php app.php m:a
@ -152,7 +148,7 @@ $ php app.php m:a
5. 复制一份profile/example配置文件夹修改账号密码即可
```shell script
```shell
# 默认配置 darling {darling}是配置文件名,可任意
$ php app.php darling m:a
# 如果写了用户参数 不带m:a 与上同等效果
@ -165,7 +161,7 @@ $ php app.php m:a
7. 命令模式
```shell script
```shell
# 获取所有命令
$ php app.php
mode:app m:a [主要模式] 默认功能
@ -219,30 +215,23 @@ $ php app.php test m:d -P VipPoint,Lottery # 多个插件
- 通过环境变量进行传入
```shell script
```shell
$ docker run -itd --rm -e USER_NAME=你的B站登录账号 -e USER_PASSWORD=你的B站密码 lkeme/bilihelper-personal
```
- 通过配置文件进行传入(能保留登录状态,自定义配置)
[//]: # (1. 下载[配置文件]&#40;https://raw.githubusercontent.com/lkeme/BiliHelper-personal/master/conf/user.ini.example&#41;)
[//]: # (2. 修改)
1.
下载 [配置文件夹](https://github.com/lkeme/BiliHelper-personal/tree/master/profile) `注意是文件夹,可以完整下载后提出来`
2. 重命名 `profile/example -> profile/user` , 修改 `profile/user/config/user.ini`
1. 下载 [代码压缩包](https://ghfast.top/https://github.com/lkeme/BiliHelper-personal/archive/refs/heads/master.zip),解压后提取`profile`目录
2. 将`profile/example`重命名为`profile/user`, 修改 `profile/user/config/user.ini`
3. 通过下面的命令进行挂载并运行
```shell script
```shell
$ docker run -itd --rm -v /path/to/your/confFilePath:/app/profile/user lkeme/bilihelper-personal
```
- 版本兼容
```shell script
```shell
$ -e VERSION=1 # 使用 版本 V1.x.x(兼容处理)
$ -e VERSION=2 # 使用 版本 V2.x.x(默认选项)
```
@ -251,7 +240,7 @@ $ -e VERSION=2 # 使用 版本 V2.x.x(默认选项)
> 以下加速镜像均为网络收集,感谢公益提供者,如有问题请联系删除
```shell script
```shell
$ -e MIRRORS=0 # 使用 github.com(RAW|源站|默认)
$ -e MIRRORS=1 # 使用 ghfast.top(US|美国)
$ -e MIRRORS=2 # 使用 gitclone.com(CN|中国)
@ -261,13 +250,22 @@ $ -e MIRRORS=5 # 使用 hub.gitmirror.com(US|美国)
$ -e MIRRORS=custom -e CUSTOM_CLONE_URL=https://github.com/lkeme/BiliHelper-personal.git # 使用 自定义克隆地址
```
- 相关参数
- 👉 相关参数
```ps
-it 前台运行
-itd 后台运行
-v 本地文件:容器内部文件 ==> 挂载本地文件到容器中。本地文件路径随便变,容器内部文件路径不能变。
```
| 选项 | 简单易懂的含义 |
|--------|----------------------------------------------------|
| `-i` | 让你能往容器里输入内容(保持输入通道打开) |
| `-t` | 给容器“配一个键盘和屏幕”,让它像在电脑前运行一样 |
| `-d` | 让容器在后台悄悄运行,不占当前窗口 |
| `--rm` | 容器一停止,自动删掉它,不留下“垃圾”。(临时测试用,跑完就干净删除,省得手动 docker rm |
| `-v` | 把电脑上的文件夹或文件“共享”给容器用(双向同步) |
- ✅ 组合小贴士
| 组合 | 含义 | 必须 |
|--------|----------------------|----|
| `-it` | 搭配使用,就像“打开一个能打字的控制台” | ✔ |
| `-itd` | 既能输入又有终端,还在后台跑 | ✔ |
- -v模式使用短信登录
@ -275,15 +273,18 @@ $ -e MIRRORS=custom -e CUSTOM_CLONE_URL=https://github.com/lkeme/BiliHelper-pers
```shell
$ docker attach 容器ID
$ docker attach --sig-proxy=false 容器ID # 关闭信号代理:本地终端按键(如 Ctrl+C不会转发给容器进程防止误关闭容器
```
```
Q: 容器停止后,容器不见了?
A: 请删除运行时的 --rm 参数
Q: 短信发送后,容器没有等待输入验证码就退出了?
A: 检查docker运行参数是否少了(-it/-itd)参数。
Q: docker attach方式使用ctrl+c退出容器容器会停止运行怎么办
A: 请用ctrl+p+q退出容器容器不会停止运行。
A1: 添加-sig-proxy=false参数docker attach --sig-proxy=false 容器IDctrl+c退出容器容器不会停止运行。
Q: 使用portainer容器管理新建的容器命令行无法输入直接验证失败怎么办
A: 在容器设置Advanced container settings -> Commands & logging -> Console -> 勾选 Interactive & TTY (-i -t) ,保存后重新部署容器即可。
@ -293,7 +294,7 @@ A: 在容器设置Advanced container settings -> Commands & logging -> Console -
- 不需要自动更新
```shell script
```shell
$ -e AUTO_UPDATE=0 # 不自动更新
```
@ -404,7 +405,7 @@ APP_CALLBACK="https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<CHAR_ID>&
通常可以在直播间页面的 url 获取到它
```
http://live.bilibili.com/9522051
https://live.bilibili.com/9522051
```
长位直播间ID获取

View File

@ -16,7 +16,8 @@
*/
use Bhp\Api\Vip\ApiExperience;
use Bhp\Api\Vip\ApiPrivilege;
use Bhp\Api\Vip\ApiPrivilegeAssets;
use Bhp\Api\Vip\ApiVipCenter;
use Bhp\Log\Log;
use Bhp\Plugin\BasePlugin;
use Bhp\Plugin\Plugin;
@ -41,60 +42,6 @@ class VipPrivilege extends BasePlugin
'cycle' => '24(小时)', // 运行周期
];
/**
* @var array|string[]
* BCoin: 1,
* MallCoupon: 2,
* ComicCoupon: 3,
* FreightCoupon: 4,
* ComicMallCoupon: 5,
* GarbFreeCoupon: 6,
* CheeseClasseCoupon: 7,
* KingOfGloryCoupon: 8,
* LevelAcceleration: 9,
* CakeCoupon: 10,
* MovieCoupon: 11,
* DisneyCoupon: 12,
* BirthdayImage: 13,
* MovieVoucher: 14,
* StarBox: 15,
* MagicStone: 16,
* GameCoupon: 17
*/
protected array $privilege = [
0 => '未知奖励0(未知奖励0)',
1 => '年度专享B币赠送(B币券)',
2 => '年度专享会员购优惠券(会员购优惠券)',
3 => '年度专享漫画礼包(漫画福利券)',
4 => '大会员专享会员购包邮券(会员购包邮券)',
5 => '年度专享漫画礼包(漫画商城优惠券)',
6 => '大会员专享会员体验卡(装扮体验卡)',
7 => '大会员专享课堂优惠券(课堂优惠券)',
8 => '大会员专享王者荣耀优惠券(游戏优惠券)',
9 => '会员观看任意1个视频即可领取日限1次(额外经验)',
10 => '大会员专享蛋糕优惠券(蛋糕优惠券)',
11 => '大会员专享电影优惠券(电影优惠券)',
12 => '大会员专享迪士尼优惠券(迪士尼优惠券)',
13 => '大会员专享生日礼图(生日礼图)',
14 => '大会员专享电影券(电影券)',
15 => '年度专享会员购星光宝盒88折券(折扣券)',
16 => '大会员专享会员购10魔晶(魔晶)',
17 => '大会员专享游戏优惠券(游戏优惠券)',
];
/**
* @var array|string[]
*/
protected array $privilege_blacklists = [
18 => '淘宝账号查询异常,请退出重试',
20 => '饿了么领取活动已经过期~',
21 => '超大会员身份状态异常',
24 => '请求错误', // 未知
25 => '请求错误', // 未知
26 => '请求错误', // 正式大会员专属票务优惠券-229减18
27 => '请求错误', // 正式漫展-大会员专属票务优惠券169减10
];
/**
* @param Plugin $plugin
*/
@ -121,6 +68,7 @@ class VipPrivilege extends BasePlugin
TimeLock::setTimes(TimeLock::timing(23) + mt_rand(10, 30) * 60);
}
/**
* 领取
* @return void
@ -131,7 +79,12 @@ class VipPrivilege extends BasePlugin
// 如果为年度大会员
if (!User::isYearVip('大会员权益')) return;
//
$privilege_list = $this->filterCanReceive($this->myVipPrivilege());
$privilege_list = array_merge($this->vipExtraEx(), $this->filterCanReceive());
if (empty($privilege_list)) {
Log::info('大会员权益: 当前无可领取权益');
return;
}
Log::info('大会员权益: 可领取权益数 ' . count($privilege_list));
//
foreach ($privilege_list as $privilege) {
@ -140,26 +93,103 @@ class VipPrivilege extends BasePlugin
// 特殊类型 9 每日10经验 需要观看视频
if ($privilege['type'] == 9) {
// 领取额外经验
$this->myVipExtraExp();
$this->extraExp();
continue;
}
// 领取奖励
$this->myVipPrivilegeReceive($privilege['type']);
$this->privilegeAssetReceive($privilege);
}
}
/**
* 大会员额外权益
* @return array|array[]
*/
protected function vipExtraEx(): array
{
$response = ApiVipCenter::v2();
//
if ($response['code']) {
Log::warning("大会员权益: 获取大会员额外经验领取状态失败 {$response['code']} -> {$response['message']}");
return [];
}
//data.experience.state 0-未领取 1-已领取
if (isset($response['data']['experience']['state']) && $response['data']['experience']['state'] == 0) {
return [
[
'type' => 9,
'title' => '专属等级加速包',
'token' => '',
'state' => 0,
'customized_text' => '每日10经验',
]
];
}
return [];
}
/**
* 过滤可领取的权益
* @param array $privilege_list
* @return array
*/
protected function filterCanReceive(array $privilege_list): array
protected function filterCanReceive(): array
{
// 是否领取状态 0未兑换 | 1已兑换 | 2未完成若需要完成
// 黑名单
return array_filter($privilege_list, function ($privilege) {
return $privilege['state'] == 0 && !array_key_exists($privilege['type'], $this->privilege_blacklists);
$response = ApiPrivilegeAssets::list();
// 请求失败
if ($response['code']) {
Log::warning("大会员权益: 获取APP端权益列表失败 {$response['code']} -> {$response['message']}");
return [];
}
// 过滤tabs
$tab = array_filter($response['data']['tabs'], function ($tab) {
return $tab['name'] == '站内福利' && $tab['type'] == 1 && $tab['type_code'] == 'welfare';
});
if (empty($tab)) {
Log::warning("大会员权益: 获取APP端权益列表失败未找到站内福利");
return [];
}
$tab = array_values($tab)[0];
/// 遍历groups
$privilege_list = [];
foreach ($tab['groups'] as $group) {
// 跳过年度专享游戏礼包
if (isset($group['title']) && $group['title'] === '年度专享游戏礼包') {
continue;
}
// 特色权益二选一只选B币券
if (isset($group['title']) && $group['title'] === '特色权益二选一') {
foreach ($group['privilege_skus'] as $sku) {
if ($sku['title'] === 'B币券' && isset($sku['exchange']['can_exchange'], $sku['exchange']['hit_exchange_limit']) && $sku['exchange']['can_exchange'] && !$sku['exchange']['hit_exchange_limit']) {
$customized_text = $this->getCustomizedText($sku);
$privilege_list[] = [
'type' => $sku['type'],
'title' => $sku['title'],
'token' => $sku['token'],
'state' => $sku['exchange']['state'] ?? 0,
'customized_text' => $customized_text,
];
break; // 只选一个
}
}
continue;
}
// 其他group遍历privilege_skus
foreach ($group['privilege_skus'] as $sku) {
if (isset($sku['exchange']['can_exchange'], $sku['exchange']['hit_exchange_limit']) && $sku['exchange']['can_exchange'] && !$sku['exchange']['hit_exchange_limit']) {
$customized_text = $this->getCustomizedText($sku);
$privilege_list[] = [
'type' => $sku['type'],
'title' => $sku['title'],
'token' => $sku['token'],
'state' => $sku['exchange']['state'] ?? 0,
'customized_text' => $customized_text,
];
}
}
}
//
return $privilege_list;
}
@ -167,7 +197,7 @@ class VipPrivilege extends BasePlugin
* 大会员额外经验
* @return void
*/
protected function myVipExtraExp(): void
protected function extraExp(): void
{
$response = ApiExperience::add();
//
@ -182,54 +212,35 @@ class VipPrivilege extends BasePlugin
/**
* 获取我的大会员权益列表
* @return array
*/
protected function myVipPrivilege(): array
{
// {"code":0,"message":"0","ttl":1,"data":{"list":[{"type":1,"state":0,"expire_time":1622476799},{"type":2,"state":0,"expire_time":1622476799}]}}
$response = ApiPrivilege::my();
//
if ($response['code']) {
Log::warning("大会员权益: 获取权益列表失败 {$response['code']} -> {$response['message']}");
return [];
} else {
Log::info('大会员权益: 获取权益列表成功 ' . count($response['data']['list']));
return $response['data']['list'];
}
}
/**
* 领取我的大会员权益
* @param int $type
* 领取大会员权益
* @param array $asset
* @throws NoLoginException
*/
protected function myVipPrivilegeReceive(int $type): void
protected function privilegeAssetReceive(array $asset): void
{
// {"code":0,"message":"0","ttl":1}
// {"code":73319,"message":"73319","ttl":1}
// {-101: "账号未登录", -111: "csrf 校验失败", -400: "请求错误", 69800: "网络繁忙 请稍后重试", 69801: "你已领取过该权益"}
$response = ApiPrivilege::receive($type);
// 判断type是否在$this->privilege
if (!array_key_exists($type, $this->privilege)) {
$type = "未知奖励$type";
} else {
$type = $this->privilege[$type];
}
$response = ApiPrivilegeAssets::exchange($asset['token']);
//
switch ($response['code']) {
case -101:
throw new NoLoginException($response['message']);
case 0:
Log::notice("大会员权益: 领取权益[$type]成功");
break;
case 73319:
Log::warning("大会员权益: 领取权益[$type]失败,暂时未到可领取时间");
Log::notice("大会员权益: 领取权益[{$asset['title']} * {$asset['customized_text']}]成功");
break;
default:
Log::warning("大会员权益: 领取权益[$type]失败, {$response['code']} -> {$response['message']}");
Log::warning("大会员权益: 领取权益[{$asset['title']} * {$asset['customized_text']}]失败 {$response['code']} -> {$response['message']}");
break;
}
}
/**
* 获取并格式化权益自定义文本
* @param array $sku
* @return string
*/
protected function getCustomizedText(array $sku): string
{
$customized = $sku['icon']['customized'] ?? [];
if (empty($customized)) return '';
return ($customized['number'] ?? '') . ($customized['currency_symbol'] ?? '') . ($customized['unit'] ?? '') . ($customized['logo_text'] ?? '');
}
}

View File

@ -3,8 +3,8 @@ device_version: 0.0.1
app:
bili_a: # Android
package: "tv.danmaku.bili"
version: "8.59.0"
build: "8590200"
version: "8.61.0"
build: "8610300"
channel: "bili"
device: "phone"
mobi_app: "android"
@ -15,7 +15,7 @@ app:
secret_key: "NTYwYzUyY2NkMjg4ZmVkMDQ1ODU5ZWQxOGJmZmQ5NzM"
app_key_n: "NzgzYmJiNzI2NDQ1MWQ4Mg=="
secret_key_n: "MjY1MzU4M2M4ODczZGVhMjY4YWI5Mzg2OTE4YjFkNjU="
statistics: '{"appId":1,"platform":3,"version":"8.59.0","abtest":""}'
statistics: '{"appId":1,"platform":3,"version":"8.61.0","abtest":""}'
bili_i: # IOS
app_key: "MjdlYjUzZmM5MDU4ZjhjMw=="
secret_key: "YzJlZDUzYTc0ZWVlZmUzY2Y5OWZiZDAxZDhjOWMzNzU="

View File

@ -8,7 +8,7 @@
"dev_raw_url": "https://raw.githubusercontent.com/lkeme/BiliHelper-personal/dev/resources/version.json",
"master_purge_url": "https://cdn.staticaly.com/gh/lkeme/BiliHelper-personal/master/resources/version.json",
"dev_purge_url": "https://cdn.staticaly.com/gh/lkeme/BiliHelper-personal/dev/resources/version.json",
"version": "2.5.0.250823",
"update_time": "2025-08-23",
"version": "2.5.1.250904",
"update_time": "2025-09-04",
"update_description": "程序有更新,请及时线上查看更新哦~"
}

View File

@ -0,0 +1,66 @@
<?php declare(strict_types=1);
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2018 ~ 2026
*
* _____ _ _ _ _ _ _____ _ _____ _____ _____
* | _ \ | | | | | | | | | | | ____| | | | _ \ | ____| | _ \ & l、
* | |_| | | | | | | | | |_| | | |__ | | | |_| | | |__ | |_| | (゚、
* | _ { | | | | | | | _ | | __| | | | ___/ | __| | _ /   \、゙ ~ *
* | |_| | | | | |___ | | | | | | | |___ | |___ | | | |___ | | \ \  じしf_, )
* |_____/ |_| |_____| |_| |_| |_| |_____| |_____| |_| |_____| |_| \_\
*/
namespace Bhp\Api\Vip;
use Bhp\Request\Request;
use Bhp\Sign\Sign;
use Bhp\User\User;
class ApiPrivilegeAssets
{
/**
* @var array|string[]
*/
protected static array $headers = [
'Referer' => 'https://big.bilibili.com/mobile/cardBag?closable=1&navhide=1&tab=all'
];
/**
* 获取大会员权益列表
* @return array
*/
public static function list(): array
{
$user = User::parseCookie();
//
$url = 'https://api.bilibili.com/x/vip/privilege_assets/list';
$payload = [
'csrf' => $user['csrf'],
];
$headers = array_merge([], self::$headers);
return Request::getJson(true, 'app', $url, Sign::common($payload), $headers);
}
/**
* 兑换大会员权益
* @param string $token
* @return array
*/
public static function exchange(string $token): array
{
$user = User::parseCookie();
//
$url = 'https://api.bilibili.com/x/vip/privilege_assets/exchange';
$payload = [
'token' => $token,
'csrf' => $user['csrf'],
];
$headers = array_merge([], self::$headers);
return Request::postJson(true, 'app', $url, Sign::common($payload), $headers);
}
}

View File

@ -0,0 +1,48 @@
<?php declare(strict_types=1);
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2018 ~ 2026
*
* _____ _ _ _ _ _ _____ _ _____ _____ _____
* | _ \ | | | | | | | | | | | ____| | | | _ \ | ____| | _ \ & l、
* | |_| | | | | | | | | |_| | | |__ | | | |_| | | |__ | |_| | (゚、
* | _ { | | | | | | | _ | | __| | | | ___/ | __| | _ /   \、゙ ~ *
* | |_| | | | | |___ | | | | | | | |___ | |___ | | | |___ | | \ \  じしf_, )
* |_____/ |_| |_____| |_| |_| |_| |_____| |_____| |_| |_____| |_| \_\
*/
namespace Bhp\Api\Vip;
use Bhp\Request\Request;
use Bhp\Sign\Sign;
use Bhp\User\User;
class ApiVipCenter
{
/**
* @var array|string[]
*/
protected static array $headers = [
'Referer' => 'https://big.bilibili.com/mobile/index'
];
/**
* 大会员中心
* @return array
*/
public static function v2(): array
{
$user = User::parseCookie();
//
$url = 'https://api.bilibili.com/x/vip/web/vip_center/v2';
$payload = [
'csrf' => $user['csrf'],
];
$headers = array_merge([], self::$headers);
return Request::getJson(true, 'app', $url, Sign::common($payload), $headers);
}
}