diff --git a/README.md b/README.md
index ab41f60..dc3e7c2 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,7 @@ Group: [602815575](https://jq.qq.com/?_wv=1027&k=UaalVexM) | **请不要来问
| LiveReservation | 0.0.1 | 预约直播有奖 | Lkeme | 1109 | 1-3(小时) | √ |
| LiveGoldBox | 0.0.1 | 直播金色宝箱(实物抽奖) | Lkeme | 1110 | 6-10(分钟) | √ |
| AwardRecords | 0.0.1 | 获奖记录 | Lkeme | 1111 | 5(分钟) | √ |
+| VipPoint | 0.0.1 | 大会员积分 | Lkeme | 1112 | 5(分钟) | √ |
diff --git a/docs/DOC.md b/docs/DOC.md
index 68cbf93..0b81609 100644
--- a/docs/DOC.md
+++ b/docs/DOC.md
@@ -16,15 +16,15 @@
通常使用 `composer` 工具会自动检测以下依赖问题。
-|Requirement |
-|--------------------|
-|PHP >=8.0 |
-|php_curl |
-|php_sockets |
-|php_openssl |
-|php_json |
-|php_zlib |
-|php_mbstring |
+| Requirement |
+|--------------|
+| PHP >=8.1 |
+| php_curl |
+| php_sockets |
+| php_openssl |
+| php_json |
+| php_zlib |
+| php_mbstring |
## 用户文件夹含义
@@ -173,6 +173,14 @@ $ php app.php
8. 请保证配置文件存在,否则默认加载`user`配置文件夹
+9. 单个或者多个插件测试
+
+```shell
+$ php app.php test m:d -p plugin
+$ php app.php test m:d -P plugin,plugin1
+$ php app.php test m:d -p VipPoint
+```
+

[comment]: <> (
)
@@ -195,7 +203,11 @@ $ docker run -itd --rm -e USER_NAME=你的B站登录账号 -e USER_PASSWORD=你
[//]: # (1. 下载[配置文件](https://raw.githubusercontent.com/lkeme/BiliHelper-personal/master/conf/user.ini.example))
[//]: # (2. 修改)
-1. 下载[配置文件夹](https://github.com/lkeme/BiliHelper-personal/tree/master/profile) `注意是文件夹,可以完整下载后提出来`
+
+1.
+
+下载[配置文件夹](https://github.com/lkeme/BiliHelper-personal/tree/master/profile) `注意是文件夹,可以完整下载后提出来`
+
2. 重命名 `profile/example -> profile/user` , 修改 `profile/user/config/user.ini`
3. 通过下面的命令进行挂载并运行
diff --git a/plugin/VipPoint/VipPoint.php b/plugin/VipPoint/VipPoint.php
new file mode 100644
index 0000000..41331b2
--- /dev/null
+++ b/plugin/VipPoint/VipPoint.php
@@ -0,0 +1,217 @@
+ __CLASS__, // hook
+ 'name' => 'VipPoint', // 插件名称
+ 'version' => '0.0.1', // 插件版本
+ 'desc' => '大会员积分', // 插件描述
+ 'author' => 'Lkeme',// 作者
+ 'priority' => 1112, // 插件优先级
+ 'cycle' => '5(分钟)', // 运行周期
+ ];
+
+ /**
+ * @var string
+ */
+ protected string $title = '大会员积分';
+
+ /**
+ * @var array|null
+ */
+ protected ?array $tasks = [];
+
+ /**
+ * 目标任务
+ * @var array|string[]
+ */
+ protected array $target_tasks = [
+ 'signIn' => '签到任务',
+// 'bonus' => '福利任务',
+// 'privilege' => '体验任务',
+ 'viewAnimate' => '浏览追番频道页10秒',
+ 'viewFilmChannel' => '浏览影视频道页10秒',
+// 'viewVipMall' => '浏览会员购页面10秒',
+// 'viewVideo' => '观看任意正片内容',
+// 'buyVipVideo' => '购买单点付费影片',
+// 'buyVipProduct' => '购买指定会员产品',
+// 'buyVipMall' => '购买指定会员购商品',
+ ];
+
+ /**
+ * @param Plugin $plugin
+ */
+ public function __construct(Plugin &$plugin)
+ {
+ // 时间锁
+ TimeLock::initTimeLock();
+ // 缓存
+ Cache::initCache();
+ // $this::class
+ $plugin->register($this, 'execute');
+ }
+
+ /**
+ * 执行
+ * @return void
+ */
+ public function execute(): void
+ {
+ if (TimeLock::getTimes() > time() || !getEnable('vip_point')) return;
+ //
+ $this->initTask();
+ //
+ $this->receiveTask();
+
+ }
+
+ /**
+ * @return void
+ */
+ protected function receiveTask(): void
+ {
+ // 如果为大会员
+ if (!User::isVip($this->title)) return;
+ // 获取远程任务列表
+ if (!$this->getTaskList()) {
+ TimeLock::setTimes(10 * 60);
+ return;
+ };
+ //
+ foreach ($this->target_tasks as $target => $value) {
+ // 任务完成跳过
+ if ($this->getTask($target)) continue;
+ // 未完成执行
+ $this->executeTask($target, $value);
+ //
+ TimeLock::setTimes(5 * 60);
+ // 每次执行一个任务
+ return;
+ }
+ // 全部完成
+ TimeLock::setTimes(TimeLock::timing(9));
+ return;
+ }
+
+ /**
+ * 动态执行任务
+ * @param string $target
+ * @param string $name
+ * @return void
+ */
+ protected function executeTask(string $target, string $name): void
+ {
+ $response = $this->getTask('TaskList');
+ //
+ if (!method_exists($this, $target)) {
+ failExit("VipPoint 不存在{$target}方法 请暂时关闭任务检查代码或通知开发者");
+ }
+ //
+ $this->setTask('signIn', $this->$target($response, $name));
+ }
+
+ /**
+ * @return void
+ */
+ protected function initTask(): void
+ {
+ $now = date("Y-m-d");
+ if (isset($this->tasks[$now])) return;
+ //
+ $this->setTask('start', true);
+ //
+ foreach ($this->target_tasks as $target => $_) {
+ $this->setTask($target, false);
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ protected function getTaskList(): bool
+ {
+ $response = \Bhp\Api\Api\X\VipPoint\ApiTask::combine();
+ if ($response['code']) {
+ Log::warning('大会员积分: 获取任务列表失败');
+ return false;
+ }
+ // 设置任务
+ $this->setTask('TaskList', $response);
+ return true;
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ * @return void
+ */
+ protected function setTask(string $key, mixed $value): void
+ {
+ $now = date("Y-m-d");
+ //
+ $this->tasks[$now][$key] = $value;
+ }
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ protected function getTask(string $key): mixed
+ {
+ $now = date("Y-m-d");
+ //
+ return $this->tasks[$now][$key];
+ }
+
+ /**
+ * @param string $key
+ * @return void
+ */
+ protected function delTask(string $key): void
+ {
+ $now = date("Y-m-d");
+ //
+ unset($this->tasks[$now][$key]);
+ }
+
+
+}
diff --git a/profile/example/config/user.ini b/profile/example/config/user.ini
index c1e8461..02bba1b 100644
--- a/profile/example/config/user.ini
+++ b/profile/example/config/user.ini
@@ -99,6 +99,10 @@ enable = true
[award_records]
enable = true
+; 大会员积分
+[vip_point]
+enable = false
+
#######################
# 通知设置 #
#######################
diff --git a/src/Api/Api/Pgc/Activity/Deliver/ApiTask.php b/src/Api/Api/Pgc/Activity/Deliver/ApiTask.php
new file mode 100644
index 0000000..56724bf
--- /dev/null
+++ b/src/Api/Api/Pgc/Activity/Deliver/ApiTask.php
@@ -0,0 +1,61 @@
+ 'https://big.bilibili.com/mobile/bigPoint/task'
+ ];
+
+ /**
+ * @var array|string[]
+ */
+ protected static array $payload = [
+ 'statistics' => '{"appId":1,"platform":3,"version":"6.86.0","abtest":""}',
+ ];
+
+ /**
+ * 完成任务 jp:追番页浏览 tv: 影视页浏览
+ * @param string $position
+ * @return array
+ */
+ public static function complete(string $position): array
+ {
+ //
+ $user = User::parseCookie();
+ //
+ $url = 'https://api.bilibili.com/pgc/activity/deliver/task/complete';
+ $payload = array_merge([
+ 'disable_rcmd' => '0',
+ 'position' => $position,
+ 'csrf' => $user['csrf'],
+ ], self::$payload);
+ $headers = array_merge([], self::$headers);
+ return Request::postJson(true, 'app', $url, Sign::common($payload), $headers);
+ }
+
+
+}
diff --git a/src/Api/Api/Pgc/Activity/Score/ApiTask.php b/src/Api/Api/Pgc/Activity/Score/ApiTask.php
new file mode 100644
index 0000000..1902343
--- /dev/null
+++ b/src/Api/Api/Pgc/Activity/Score/ApiTask.php
@@ -0,0 +1,100 @@
+ 'https://big.bilibili.com/mobile/bigPoint/task'
+ ];
+
+ /**
+ * @var array|string[]
+ */
+ protected static array $payload = [
+ 'statistics' => '{"appId":1,"platform":3,"version":"6.86.0","abtest":""}',
+ ];
+
+ /**
+ * 大会员签到
+ * @return array
+ */
+ public static function sign(): array
+ {
+ //
+ $user = User::parseCookie();
+ //
+ $url = 'https://api.bilibili.com/pgc/activity/score/task/sign';
+ $payload = array_merge([
+ 'disable_rcmd' => '0',
+ 'csrf' => $user['csrf'],
+ ], self::$payload);
+ $headers = array_merge([], self::$headers);
+ return Request::postJson(true, 'app', $url, Sign::common($payload), $headers);
+ }
+
+ /**
+ * 领取任务
+ * @param string $task_code
+ * @return array
+ */
+ public static function receive(string $task_code): array
+ {
+ //
+ $user = User::parseCookie();
+ //
+ $url = 'https://api.bilibili.com/pgc/activity/score/task/receive';
+ $payload = array_merge([
+ 'taskCode' => $task_code,
+ 'csrf' => $user['csrf'],
+ ], self::$payload);
+ $headers = array_merge([], self::$headers);
+ return Request::postJson(true, 'app', $url, Sign::common($payload), $headers);
+ }
+
+ /**
+ * 完成任务
+ * @param string $task_code
+ * @return array
+ */
+ public static function complete(string $task_code): array
+ {
+ //
+ $user = User::parseCookie();
+ //
+ $url = 'https://api.bilibili.com/pgc/activity/score/task/complete';
+ $payload = array_merge([
+ 'taskCode' => $task_code,
+ 'csrf' => $user['csrf'],
+ 'ts' => time(),
+ ], self::$payload);
+ $headers = array_merge([
+ 'Content-Type' => 'application/json'
+ ], self::$headers);
+ return Request::postJson(true, 'app', $url, Sign::common($payload), $headers);
+ }
+
+
+}
diff --git a/src/Api/Api/X/VipPoint/ApiTask.php b/src/Api/Api/X/VipPoint/ApiTask.php
new file mode 100644
index 0000000..585fdac
--- /dev/null
+++ b/src/Api/Api/X/VipPoint/ApiTask.php
@@ -0,0 +1,43 @@
+ 'https://big.bilibili.com/mobile/bigPoint/task'
+ ];
+
+ /**
+ * 用户信息
+ * @return array
+ */
+ public static function combine(): array
+ {
+ $url = 'https://api.bilibili.com/x/vip_point/task/combine';
+ $payload = [];
+ $headers = array_merge([], self::$headers);
+ return Request::getJson(true, 'app', $url, Sign::common($payload), $headers);
+ }
+}
diff --git a/src/Api/Show/Api/Activity/Fire/Common/ApiEvent.php b/src/Api/Show/Api/Activity/Fire/Common/ApiEvent.php
new file mode 100644
index 0000000..e6434c9
--- /dev/null
+++ b/src/Api/Show/Api/Activity/Fire/Common/ApiEvent.php
@@ -0,0 +1,63 @@
+ 'https://big.bilibili.com/mobile/bigPoint/task'
+ ];
+
+ /**
+ * @var array|string[]
+ */
+ protected static array $payload = [
+ 'statistics' => '{"appId":1,"platform":3,"version":"6.86.0","abtest":""}',
+ ];
+
+ /**
+ * @return array
+ */
+ public static function dispatch(): array
+ {
+ //
+ $user = User::parseCookie();
+ //
+ $url = 'https://show.bilibili.com/api/activity/fire/common/event/dispatch';
+ $payload = array_merge([
+ 'msource' => 'member_integral_browse',
+ 'action' => 'browse_all',
+ 'eventId' => 'hevent_oy4b7h3epeb',
+ 'eventTime' => '10',
+ 'csrf' => $user['csrf'],
+ ], self::$payload);
+ $headers = array_merge([
+ 'content-type'=> 'application/json; charset=utf-8',
+ ], self::$headers);
+ return Request::postJson(true, 'app', $url, Sign::common($payload), $headers);
+ }
+
+}
diff --git a/src/Helpers.php b/src/Helpers.php
index 8d1a8e8..7f8cd66 100644
--- a/src/Helpers.php
+++ b/src/Helpers.php
@@ -182,3 +182,25 @@ function getDevice(string $key, mixed $default = null, string $type = 'default')
//{
// Cache::getInstance()->_set($key, $data, $extra_name);
//}
+
+/**
+ * @param string $dir
+ * @param array $exclude
+ * @return void
+ */
+function requireDir(string $dir, array $exclude = []): void
+{
+ $handle = opendir($dir);//打开文件夹
+ while (false !== ($file = readdir($handle))) {//读取文件
+ if ($file != '.' && $file != '..') {
+ if (in_array($file, $exclude)) continue;
+ //
+ $filepath = $dir . '/' . $file;//文件路径
+ if (filetype($filepath) == 'dir') {//如果是文件夹
+ requireDir($filepath);//继续读
+ } else {
+ include_once($filepath);//引入文件
+ }
+ }
+ }
+}
diff --git a/src/User/User.php b/src/User/User.php
index 30b4467..c8600f6 100644
--- a/src/User/User.php
+++ b/src/User/User.php
@@ -51,12 +51,15 @@ class User extends SingleTon
];
}
+
/**
- * 是否为有效年度大会员
+ * 是否是有效大会员
* @param string $title
+ * @param array $scope
+ * @param string $info
* @return bool
*/
- public static function isYearVip(string $title = '用户信息'): bool
+ public static function isVip(string $title = '用户信息', array $scope = [1, 2], string $info = '大会员'): bool
{
$response = ApiUser::userInfo();
//
@@ -65,13 +68,25 @@ class User extends SingleTon
return false;
}
//
- if ($response['data']['vip_type'] == 2 && $response['data']['vip_due_date'] > Common::getUnixTimestamp()) {
- Log::info("$title: 获取大会员信息成功 是有效的年度大会员");
+ if (in_array($response['data']['vip_type'], $scope) && $response['data']['vip_due_date'] > Common::getUnixTimestamp()) {
+ Log::info("$title: 获取大会员信息成功 是有效的$info ");
return true;
}
//
- Log::warning("$title: 获取大会员信息成功 不是年度大会员或已过期");
+ Log::warning("$title: 获取大会员信息成功 不是{$info}或已过期");
return false;
}
-}
\ No newline at end of file
+ /**
+ * 是否为有效年度大会员 0:无会员 1:月会员 2:年会员
+ * @param string $title
+ * @param array $scope
+ * @param string $info
+ * @return bool
+ */
+ public static function isYearVip(string $title = '用户信息', array $scope = [2], string $info = '年度大会员'): bool
+ {
+ return self::isVip($title, $scope, $info);
+ }
+
+}