diff --git a/README.md b/README.md index 032fba3..69dfe81 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@

- + diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5b09fa3..3184aff 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,6 +8,25 @@ [comment]: <> () +## v2.5.1.250904 alpha (2025-09-04) + +### Added + +- + +### Changed + +- 更新设备信息 +- 更新部分使用文档 + +### Fixed + +- 尝试修复年度大会员领取权益**特色权益二选一** + +### Remarks + +- + ## v2.5.0.250823 alpha (2025-08-23) ### Added diff --git a/docs/DOC.md b/docs/DOC.md index ea4a21e..cf64d52 100644 --- a/docs/DOC.md +++ b/docs/DOC.md @@ -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 (-o)) - -[comment]: <> (composer dumpautoload (-o)) - 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. 下载[配置文件](https://raw.githubusercontent.com/lkeme/BiliHelper-personal/master/conf/user.ini.example)) - -[//]: # (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 容器ID,ctrl+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/sendMessage?chat_id=& 通常可以在直播间页面的 url 获取到它 ``` -http://live.bilibili.com/9522051 +https://live.bilibili.com/9522051 ``` 长位直播间ID获取 diff --git a/plugin/VipPrivilege/VipPrivilege.php b/plugin/VipPrivilege/VipPrivilege.php index 5053a20..41e8b31 100644 --- a/plugin/VipPrivilege/VipPrivilege.php +++ b/plugin/VipPrivilege/VipPrivilege.php @@ -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'] ?? ''); + } } diff --git a/profile/example/device/device.yaml b/profile/example/device/device.yaml index c87c377..f3bfb6b 100644 --- a/profile/example/device/device.yaml +++ b/profile/example/device/device.yaml @@ -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=" diff --git a/resources/version.json b/resources/version.json index 7e3bcf1..1c9c436 100644 --- a/resources/version.json +++ b/resources/version.json @@ -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": "程序有更新,请及时线上查看更新哦~" } diff --git a/src/Api/Vip/ApiPrivilegeAssets.php b/src/Api/Vip/ApiPrivilegeAssets.php new file mode 100644 index 0000000..c4244a3 --- /dev/null +++ b/src/Api/Vip/ApiPrivilegeAssets.php @@ -0,0 +1,66 @@ + '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); + } +} diff --git a/src/Api/Vip/ApiVipCenter.php b/src/Api/Vip/ApiVipCenter.php new file mode 100644 index 0000000..c2db36e --- /dev/null +++ b/src/Api/Vip/ApiVipCenter.php @@ -0,0 +1,48 @@ + '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); + } +}