From 063b349fa2769a6d6c6ca288b3a38ef745b142bc Mon Sep 17 00:00:00 2001 From: Lkeme <19500576+lkeme@users.noreply.github.com> Date: Mon, 31 Jul 2023 21:38:38 +0800 Subject: [PATCH] [update] - --- .gitignore | 1 + plugin/DailyGold/DailyGold.php | 68 ++++-- plugin/Lottery/Lottery.php | 249 ++++++++++++++------ plugin/Lottery/LotteryInfo.php | 2 + plugin/MainSite/MainSite.php | 2 +- plugin/PluginTemplate/PluginTemplate.php | 18 +- plugin/PolishMedal/PolishMedal.php | 2 +- profile/example/config/user.ini | 4 +- src/Api/Space/ApiReservation.php | 1 + src/Api/XLive/AppUcenter/V1/ApiUserTask.php | 4 +- src/Plugin/Plugin.php | 2 +- src/TimeLock/TimeLock.php | 23 +- 12 files changed, 268 insertions(+), 108 deletions(-) diff --git a/.gitignore b/.gitignore index 8ae8673..20f0ad0 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ README1.md script.php test.php +test1.php index1.php # ignore all files in lib/ diff --git a/plugin/DailyGold/DailyGold.php b/plugin/DailyGold/DailyGold.php index c31765f..d3c1547 100644 --- a/plugin/DailyGold/DailyGold.php +++ b/plugin/DailyGold/DailyGold.php @@ -61,18 +61,20 @@ class DailyGold extends BasePlugin $up_uid = (int)getConf('daily_gold.target_up_id', ''); $up_room_id = (int)getConf('daily_gold.target_room_id', ''); if (!$up_room_id || !$up_uid) return; - // - $process = $this->getUserTaskProgress(); + // {"task_id":45,"type":2,"goal_type":2,"target":0,"task_title":"看新主播30秒,并发弹幕鼓励TA","title_param":["30","1"],"task_sub_title":"点击「去看看」做任务","sub_title_param":null,"total_reward":20,"received_reward":0,"reward_type":1,"rules":"1.必须点击“去看看”按钮,进入的新主播直播间才计为任务直播间,在这些直播间内才可完成本任务;\n2.每个任务直播间,每天仅可完成1次任务,或领取1次奖励,请上下滑浏览更多任务直播间,才能完成更多任务;\n3.观看时长要求:30秒需单次在同一个任务直播间内连续观看,退房后或上下滑后,观看时长将重新计算,建议观看时多和主播互动哦;\n4.发送弹幕要求:建议发送友好的,跟当前直播内容相关的弹幕,如鼓励夸赞主播、鼓励主播表演才艺等,不能是纯数字、纯字母、纯符号等无意义内容,也不能是表情包,且字数必须大于等于3,内容符合哔哩哔哩社区公约,否则可能不计为有效弹幕;\n5.由于参与人数较多,任务直播间可能会失效,若在任务直播间打开福利中心,本任务按钮显示“去看看”,则说明本任务直播间已失效,请上下滑浏览更多任务直播间。","priority":0,"progress":0,"status":1,"schema_dst":0,"btn_text":"暂无新任务","finished_text":"观看任务已达成","finished_sub_text":"","num":1,"available":0}" + $process = $this->getUserUnfinishedTask($up_uid); + switch ($process) { - case -3: - // 领取完成 - TimeLock::setTimes(TimeLock::timing(7, 0, 0, true)); + case 0: + // 默认一次弹幕进度 + $this->sendDM($up_room_id, Fake::emoji(true)); + TimeLock::setTimes(mt_rand(30, 60) * 60); break; case -1: // 获取失败 TimeLock::setTimes(10 * 60); break; - case 0: + case -2: // 领取ing if (!$this->userTaskReceiveRewards($up_uid)) { // 领取失败 TODO @@ -80,46 +82,70 @@ class DailyGold extends BasePlugin // [message] => 领取失败,请重试 // [data][num] => 0 TimeLock::setTimes(10 * 60); - }else{ + } else { // TODO 因活动变动,每个人的任务详情不一致,暂时解决方案,可能会影响电池的获取 // 领取完成 TimeLock::setTimes(TimeLock::timing(7, 0, 0, true)); } break; + case -3: + // 领取完成 + TimeLock::setTimes(TimeLock::timing(7, 0, 0, true)); + break; default: - // 默认一次弹幕进度 - $this->sendDM($up_room_id, Fake::emoji(true)); - TimeLock::setTimes(mt_rand(30, 60) * 60); break; } } /** * 获取任务进度 + * @param int $up_id * @return int */ - protected function getUserTaskProgress(): int + protected function getUserUnfinishedTask(int $up_id): int { - $response = ApiUserTask::getUserTaskProgress(); + $response = ApiUserTask::getUserTaskProgress($up_id); + // if ($response['code']) { Log::warning("每日电池: 获取任务进度失败 {$response['code']} -> {$response['message']}"); return -1; } - // - $target = (int)$response['data']['target']; - $progress = (int)$response['data']['progress']; - Log::info("每日电池: 当前任务进度 $progress/$target"); // 领取完成 if ($response['data']['status'] == 3) { + Log::info("每日电池: 账号已经领取奖励,故跳过"); return -3; } - // 可以领取 -// if ($response['data']['status'] == 2) { -// return 0; -// } - return (int)($response['data']['target'] - $response['data']['progress']); + // + if ($response['data']['is_surplus'] === -1) { + Log::info("每日电池: 账号无法完成该任务,故跳过"); + return -3; + } + // + if (is_null($response['data']['task_list'])) { + Log::info("每日电池: 没有可执行任务,故跳过"); + return -3; + } + // + $filteredArray = array_filter($response['data']['task_list'], function ($element) { + return ($element['status'] != 3 && str_contains($element['task_title'], '5条弹幕')); + }); + if (empty($filteredArray)) { + Log::info("每日电池: 没有可执行任务,故跳过"); + return -3; + } + // + $filteredArray = array_filter($filteredArray, function ($element) { + return ($element['status'] == 2); + }); + if ($filteredArray){ + Log::info("每日电池: 任务已经完成,可以领取奖励"); + return -2; + } + // + return 0; } + /** * 发送弹幕(外部调用APP) * @param int $room_id diff --git a/plugin/Lottery/Lottery.php b/plugin/Lottery/Lottery.php index b600def..cf3ddae 100644 --- a/plugin/Lottery/Lottery.php +++ b/plugin/Lottery/Lottery.php @@ -62,7 +62,7 @@ class Lottery extends BasePlugin */ public function __construct(Plugin &$plugin) { - include_once 'LotteryInfo.php'; +// include_once 'LotteryInfo.php'; TimeLock::initTimeLock(); Cache::initCache(); $plugin->register($this, 'execute'); @@ -74,9 +74,14 @@ class Lottery extends BasePlugin */ public function execute(): void { + echo "ghahahahha"; if (!getEnable('lottery')) return; if (TimeLock::getTimes() > time() && $this->last_task_finish) return; + echo "ghahahahha"; + $this->lotteryTask(); + echo "ghahahahha"; + // 2-6小时 未完成6-10秒 TimeLock::setTimes($this->last_task_finish ? (mt_rand(2, 6) * 60 * 60) : mt_rand(6, 10)); } @@ -87,12 +92,13 @@ class Lottery extends BasePlugin */ protected function lotteryTask(): void { - $last_lottery_id = ($tmp = Cache::get('last_lottery_id')) ? $tmp : $this->calcLastLotteryId(); +// $last_lottery_id = ($tmp = Cache::get('last_lottery_id')) ? $tmp : $this->calcLastLotteryId(); + $last_lottery_id = 3015989; $times = 0; // 参加抽奖 while (true) { - if(LotteryInfo::isExist($last_lottery_id)) continue; - if($times > 9) { +// if (LotteryInfo::isExist($last_lottery_id)) continue; + if ($times > 9) { $this->last_task_finish = false; break; } @@ -100,7 +106,7 @@ class Lottery extends BasePlugin if ($info['status'] === -9999) { // 当前抽奖不存在 $this->last_task_finish = true; break; - } else if($info['status'] === -1 || $info['status'] === 2) { // 当前抽奖无效/当前抽奖已开奖 + } else if ($info['status'] === 2) { // 当前抽奖已开奖 $last_lottery_id++; continue; } @@ -111,16 +117,16 @@ class Lottery extends BasePlugin } $times = 0; // 删除动态 - $infos = LotteryInfo::getHasLotteryList(); - foreach ($infos as $info) { - if($times > 9) { - $this->last_task_finish = false; - break; - } - //TODO 删除动态 - LotteryInfo::delete($info['lottery_id']); - $times++; - } +// $infos = LotteryInfo::getHasLotteryList(); +// foreach ($infos as $info) { +// if ($times > 9) { +// $this->last_task_finish = false; +// break; +// } +// //TODO 删除动态 +// LotteryInfo::delete($info['lottery_id']); +// $times++; +// } } /** @@ -171,101 +177,202 @@ class Lottery extends BasePlugin /** * 获取抽奖信息 - * @param int $lottery_id + * @param int $business_id * @return array */ - protected function getLotteryInfo(int $lottery_id): array + protected function getLotteryInfo(int $business_id): array { delay(3); $user = User::parseCookie(); - $url = 'https://api.vc.bilibili.com/lottery_svr/v1/lottery_svr/detail_by_lid'; + $url = 'https://api.vc.bilibili.com/lottery_svr/v1/lottery_svr/lottery_notice'; + $headers = [ + 'origin' => 'https://www.bilibili.com', + 'referer' => 'https://www.bilibili.com/' + ]; $payload = [ - 'lottery_id' => $lottery_id, + 'business_id' => $business_id, + 'business_type' => 10, // 1.转发动态 10.直播预约 'csrf' => $user['csrf'], ]; - $response = Request::getJson(true, 'pc', $url, $payload); + echo $business_id.PHP_EOL; + $response = Request::getJson(true, 'pc', $url, $payload, $headers); + print_r($response); - // 抽奖不存在 + // 抽奖不存在/请求错误/请求被拦截 if ($response['code'] === -9999 || $response['code'] === 4000014 || $response['code'] === -412) { -// if ($response['code'] === -412) { -// Log::warning("抽奖:请求被拦截,暂定无效请求"); -// } return [ 'status' => -9999, ]; } $data = $response['data']; - // business_type为0的则为无效抽奖 - if ($data['business_type'] === 0) { - return [ - 'status' => -1, - ]; - } // 已开奖 - if ($data['lottery_time'] <= time()) { + if ($data['lottery_time'] <= time()) { return [ 'status' => 2, ]; } + return [ - 'lottery_id' => $lottery_id, + 'business_id' => $business_id, // business_type=1时是动态Id business_type=10时是预约直播Id + 'lottery_id' => $data['lottery_id'], // 抽奖ID + 'lottery_time' => $data['lottery_time'], // 开奖时间 + 'lottery_detail_url' => $data['lottery_detail_url'], // 抽奖详情页 + 'need_feed' => $data['lottery_feed_limit'] === 1, // 是否需要关注 + 'need_post' => $data['need_post'] === 1, //是否需要发货地址 + 'sender_uid' => $data['sender_uid'], // 发起人UID 'status' => $data['status'], // 0 未开奖 2 已开奖 -1 已失效 -9999 不存在 'type' => $data['business_type'], // 1.转发动态 10.直播预约 - 'need_feed' => $data['lottery_feed_limit'] === 1, // 是否需要关注 - 'business_id' => $data['business_id'], // business_type=1时是动态Id business_type=10时是预约直播Id + 'ts' => $data['ts'], // 时间戳 + 'prizes' => $this->parsePrizes($data), // 奖品 ]; } + + /** + * 解析奖品 + * @param array $data + * @return string + */ + protected function parsePrizes(array $data): string + { + $prizes = ''; + $prizeData = [ + 'first_prize' => ['一等奖', 'first_prize_cmt'], + 'second_prize' => ['二等奖', 'second_prize_cmt'], + 'third_prize' => ['三等奖', 'third_prize_cmt'] + ]; + // + foreach ($prizeData as $key => $value) { + if (isset($data[$key]) && isset($data[$value[1]])) { + $prizes .= "{$value[0]}: {$data[$value[1]]} * {$data[$key]}\n"; + } + } + // + return $prizes; + } + /** * 参加抽奖 * @param array $info * @return void */ - protected function joinLottery(array $info): void - { - $dynamic_enable = getConf('lottery.dynamic_enable', false); - $live_enable = getConf('lottery.live_enable', false); - - if ($info['type'] === 1 && $dynamic_enable) { - $dynamic_id = $info['business_id']; - //TODO 转发动态 - //TODO 关注用户并放到指定分组 - } else if ($info['type'] === 10 && $live_enable) { - $reserve_id = $info['business_id']; - $this->reserveLive($reserve_id); - } - } - - /** - * 删除动态 - * @param string $dynamic_id - * @return void - */ - protected function deleteDynamic(string $dynamic_id): void - { - //TODO 删除动态 - } - - /** - * 预约直播 - * @param int $reserve_id - * @return void - */ - protected function reserveLive(int $reserve_id): void + protected function reserve(array $info): void { + // $user = User::parseCookie(); + // $url = 'https://api.vc.bilibili.com/dynamic_mix/v1/dynamic_mix/reserve_attach_card_button'; + $headers = [ + 'origin' => 'https://space.bilibili.com', + 'referer' => "https://space.bilibili.com/{$info['sender_uid']}/dynamic" + ]; $payload = [ 'cur_btn_status' => 1, - 'reserve_id' => $reserve_id, + 'dynamic_id' => $info['id_str'], + 'attach_card_type' => 'reserve', + 'reserve_id' => $info['business_id'], + 'reserve_total' => $info['reserve_total'], + 'spmid' => '', 'csrf' => $user['csrf'], ]; - $response = Request::postJson(true, 'pc', $url, $payload); - - if($response['code'] === 0 || $response['code'] === 7604003) { //预约成功/已经预约 - Log::info("抽奖: 预约直播成功 ReserveId: $reserve_id"); + // + $response = Request::postJson(true, 'pc', $url, $payload, $headers); + // + if ($response['code'] === 0 || $response['code'] === 7604003) { //预约成功/已经预约 + Log::info("抽奖: 预约直播成功 ID: {$info['business_id']} UP: {$info['sender_uid']} 预约人数: {$info['reserve_total']}"); + Log::info("抽奖: 地址: {$info['lottery_detail_url']}"); + Log::info("抽奖: 奖品: {$info['prizes']}"); } else { - Log::warning("抽奖: 预约直播失败 ReserveId: $reserve_id Error: {$response['code']} -> {$response['message']}"); + Log::warning("抽奖: 预约直播失败 ReserveId: $info[business_id] Error: {$response['code']} -> {$response['message']}"); } } + + + /** + * 提取动态参数 + * @param string $data + * @return array + */ + protected function extractDynamicParameters(string $data): array + { + $result = []; + preg_match('/"reserve_total":(\d+)/', $data, $b); // 正则匹配 + if (isset($b[1])) { + $result['reserve_total'] = $b[1]; + } + preg_match('/"reserve_total": (\d+)/', $data, $b); // 正则匹配 + if (isset($b[1])) { + $result['reserve_total'] = $b[1]; + } + preg_match('/"id_str":(\d+)/', $data, $b); // 正则匹配 + if (isset($b[1])) { + $result['id_str'] = $b[1]; + } + preg_match('/"id_str": (\d+)/', $data, $b); // 正则匹配 + if (isset($b[1])) { + $result['id_str'] = $b[1]; + } + return $result; + } + + /** + * 过滤指定动态 + * @param array $dynamic_list + * @param int $rid + * @return array + */ + protected function filterDynamic(array $dynamic_list, int $rid): array + { + foreach ($dynamic_list as $dynamic) { + $dynamic_str = json_encode($dynamic); + if (str_contains($dynamic_str, '"rid":' . $rid) || str_contains($dynamic_str, '"rid": ' . $rid)) { + return $this->extractDynamicParameters($dynamic_str); + } + } + return []; + } + + + /** + * 获取指定空间动态列表 + * @param int $host_mid + * @return array + */ + protected function fetchSpaceDynamic(int $host_mid): array + { + $url = 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space'; + $headers = [ + 'origin' => 'https://space.bilibili.com', + 'referer' => "https://space.bilibili.com/{$host_mid}/dynamic" + ]; + $payload = [ + 'offset' => '', + 'host_mid' => $host_mid, + 'timezone_offset' => '-480', + 'features' => 'itemOpusStyle' + ]; + // + $response = Request::getJson(true, 'pc', $url, $payload, $headers); + // + if ($response['code']) { + Log::warning("获取({$host_mid})空间动态失败: {$response['code']} -> {$response['message']}"); + return []; + } + // + return $response['data']['items'] ?? []; + } + + protected function joinLottery(array $info): void + { + $dynamic_list = $this->fetchSpaceDynamic($info['sender_uid']); + $dynamic = $this->filterDynamic($dynamic_list, $info['business_id']); + if (!isset($dynamic['id_str']) || !isset($dynamic['reserve_total'])) { + Log::warning("抽奖: 未找到指定动态 ReserveId: $info[business_id]"); + return; + } + // 合并数组 + $info = array_merge($info, $dynamic); + $this->reserve($info); + } + } diff --git a/plugin/Lottery/LotteryInfo.php b/plugin/Lottery/LotteryInfo.php index c4860c8..62cb53b 100644 --- a/plugin/Lottery/LotteryInfo.php +++ b/plugin/Lottery/LotteryInfo.php @@ -64,6 +64,8 @@ class LotteryInfo extends SingleTon * @param int $lottery_id * @param string $dynamic_id * @param int $lottery_time + * @param int $uid + * @param int $group_id * @return void */ public static function add(int $lottery_id, string $dynamic_id, int $lottery_time, int $uid, int $group_id): void diff --git a/plugin/MainSite/MainSite.php b/plugin/MainSite/MainSite.php index ea5a71b..e355493 100644 --- a/plugin/MainSite/MainSite.php +++ b/plugin/MainSite/MainSite.php @@ -125,7 +125,7 @@ class MainSite extends BasePlugin { if (!getConf('main_site.add_coin', false, 'bool')) return true; // 已满6级 - if (!getConf('main_site.when_lv6_stop_coin', false, 'bool')) { + if (getConf('main_site.when_lv6_stop_coin', false, 'bool')) { $userInfo = User::userNavInfo(); if ($userInfo->level_info->current_level >= 6) { Log::notice('主站任务: 已满6级, 停止投币'); diff --git a/plugin/PluginTemplate/PluginTemplate.php b/plugin/PluginTemplate/PluginTemplate.php index d30720b..774a8e3 100644 --- a/plugin/PluginTemplate/PluginTemplate.php +++ b/plugin/PluginTemplate/PluginTemplate.php @@ -27,12 +27,15 @@ class PluginTemplate extends BasePlugin */ protected ?array $info = [ 'hook' => __CLASS__, // hook - 'name' => 'PluginTemplate', // 插件名称 + 'name' => 'PolishTheMedal', // 插件名称 'version' => '0.0.1', // 插件版本 'desc' => '插件模板', // 插件描述 'author' => 'Lkeme',// 作者 'priority' => 9999, // 插件优先级 'cycle' => '1(小时)', // 运行周期 + // 新增字段 + 'start' => '08:00:00', // 插件开始日期 + 'end' => '23:00:00', // 插件结束日期 ]; /** @@ -54,11 +57,14 @@ class PluginTemplate extends BasePlugin */ public function execute(): void { -// if (TimeLock::getTimes() > time()) return; - // - // todo - // -// TimeLock::setTimes(24 * 60 * 60); + // 时间段限制 + // if (!TimeLock::isWithinTimeRange($this->info['start'], $this->info['end'])) return; + // 时间锁限制 + // if (TimeLock::getTimes() > time()) return; + + // todo ... + + //TimeLock::setTimes(24 * 60 * 60); } diff --git a/plugin/PolishMedal/PolishMedal.php b/plugin/PolishMedal/PolishMedal.php index a3464ef..c892240 100644 --- a/plugin/PolishMedal/PolishMedal.php +++ b/plugin/PolishMedal/PolishMedal.php @@ -131,7 +131,7 @@ class PolishMedal extends BasePlugin * 获取熄灭徽章 * @param bool $all */ - private static function fetchGreyMedalList(bool $all = false) + private static function fetchGreyMedalList(bool $all = false): void { $data = self::fetchMedalList(); foreach ($data as $vo) { diff --git a/profile/example/config/user.ini b/profile/example/config/user.ini index 12af4e6..099715d 100644 --- a/profile/example/config/user.ini +++ b/profile/example/config/user.ini @@ -112,13 +112,11 @@ enable = true [vip_point] enable = false -; 动态抽奖&预约直播抽奖 +; 卍预约直播抽奖 [lottery] enable = false ; 抽奖模式 0.从最新Id开始抽奖 1.从最新Id的前2400个开始抽奖 lottery_mode = 0 -; 直播预约抽奖 -live_enable = false ; 每日电池 对应直播间ID和直播间UID [daily_gold] diff --git a/src/Api/Space/ApiReservation.php b/src/Api/Space/ApiReservation.php index c344c70..e31829a 100644 --- a/src/Api/Space/ApiReservation.php +++ b/src/Api/Space/ApiReservation.php @@ -62,6 +62,7 @@ class ApiReservation 'origin' => 'https://space.bilibili.com', 'referer' => "https://space.bilibili.com/$vmid/" ]; + // {"code":75077,"message":"重复参加活动!","ttl":1} // {"code":0,"message":"0","ttl":1} return Request::postJson(true, 'pc', $url, $payload, $headers); } diff --git a/src/Api/XLive/AppUcenter/V1/ApiUserTask.php b/src/Api/XLive/AppUcenter/V1/ApiUserTask.php index ca5d73e..247a2a6 100644 --- a/src/Api/XLive/AppUcenter/V1/ApiUserTask.php +++ b/src/Api/XLive/AppUcenter/V1/ApiUserTask.php @@ -24,12 +24,14 @@ class ApiUserTask { /** * 获取任务进度 + * @param int $up_id * @return array */ - public static function getUserTaskProgress(): array + public static function getUserTaskProgress(int $up_id): array { $url = 'https://api.live.bilibili.com/xlive/app-ucenter/v1/userTask/GetUserTaskProgress'; $payload = [ + 'target_id' => $up_id, 'statistics' => getDevice('app.bili_a.statistics'), ]; diff --git a/src/Plugin/Plugin.php b/src/Plugin/Plugin.php index f54d7a4..067a758 100644 --- a/src/Plugin/Plugin.php +++ b/src/Plugin/Plugin.php @@ -76,7 +76,7 @@ class Plugin extends SingleTon /** * 这个是全局使用的触发钩子动作方法 * @param string $hook - * @param string $data + * @param mixed ...$params * @return string */ public function trigger(string $hook, mixed...$params): string diff --git a/src/TimeLock/TimeLock.php b/src/TimeLock/TimeLock.php index 41f0388..7ec8a61 100644 --- a/src/TimeLock/TimeLock.php +++ b/src/TimeLock/TimeLock.php @@ -79,7 +79,7 @@ class TimeLock extends SingleTon $class_name = self::getInstance()->getCallClassName(); self::getInstance()->locks[$class_name]['times'] = time() + $times; // - Schedule::set($class_name,self::getInstance()->locks[$class_name]['times']); + Schedule::set($class_name, self::getInstance()->locks[$class_name]['times']); } /** @@ -153,6 +153,23 @@ class TimeLock extends SingleTon return false; } + /** + * 判断是否在时间内 + * @param string $start + * @param string $end + * @return bool + */ + public static function isWithinTimeRange(string $start, string $end):bool + { + // date_default_timezone_set('Asia/Shanghai'); + $startTime = strtotime(date($start)); + $endTime = strtotime(date($end)); + $nowTime = time(); + // + return $nowTime >= $startTime && $nowTime <= $endTime; + } + + /** * 获取调用者类名 * @return string @@ -163,9 +180,9 @@ class TimeLock extends SingleTon $backtraces = debug_backtrace(); $temp = pathinfo(basename($backtraces[1]['file']))['filename']; // - if ($temp == basename(str_replace('\\', '/', __CLASS__))){ + if ($temp == basename(str_replace('\\', '/', __CLASS__))) { return pathinfo(basename($backtraces[2]['file']))['filename']; - }else{ + } else { return $temp; } }