diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77fbdd1..87482ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,23 @@
# Release Notes
# 本项目Log
+## v0.8.1.210423 alpha (2021-04-23)
+
+### Added
+-
+
+### Changed
+- 更新天选敏感词
+- 更新活动列表
+- 优化直播间心跳
+-
+
+### Fixed
+-
+
+### Remarks
+-
+
## v0.8.0.210327 alpha (2021-03-27)
### Added
diff --git a/DOC.md b/DOC.md
index afce528..85879fc 100644
--- a/DOC.md
+++ b/DOC.md
@@ -2,7 +2,7 @@

-
+
@@ -17,7 +17,7 @@ B 站直播实用脚本
|--------------------|--------------------|--------------------|
|Login |21.03.27 |账号登录 |
|Schedule |21.03.27 |休眠控制 |
-|MainSite |21.03.27 |主站助手 |
+|MainSite |21.03.27 |主站助手 |
|Daily |21.03.27 |每日礼包 |
|Heart |21.03.27 |双端心跳 |
|DailyTask |21.03.27 |每日任务 |
diff --git a/README.md b/README.md
index cf48b01..c26e1bc 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg) | **仅用于BUG提交
## 公告
-> Personal Edition **0.8.0.210327 alpha**
+> Personal Edition **0.8.1.210423 alpha**
```notice
---- 免费的东西总是得不到人的珍惜。
diff --git a/data/activity_infos.json b/data/activity_infos.json
index 3047d95..90c1d60 100644
--- a/data/activity_infos.json
+++ b/data/activity_infos.json
@@ -41,7 +41,7 @@
"follow": "false",
"share": "true",
"draw_times": 2,
- "expire_at": "2021-04-15 11:59:59"
+ "expire_at": "2021-05-23 11:59:59"
},
{
"url": "https://www.bilibili.com/blackboard/activity-QEya2bouhQ.html",
@@ -63,19 +63,30 @@
"follow": "false",
"share": "true",
"draw_times": 1,
- "expire_at": "2021-04-30 23:59:59",
+ "expire_at": "2021-05-30 23:59:59",
"remarks": "时间不名,暂定一个月。"
},
{
- "url": "https://www.bilibili.com/blackboard/activity-M22oqFLY1w.html",
- "title": "最强搞事王",
+ "url": "https://www.bilibili.com/blackboard/activity-aT7zphkwF1.html",
+ "title": "初夏逛吃大会",
"description": "活动期间每天分享页面,新增一次机会。",
- "sid": "e168f825-8be6-11eb-8597-246e966235d8",
+ "sid": "01aff78a-9e1a-11eb-8597-246e966235d8",
"login": "true",
"follow": "false",
"share": "true",
"draw_times": 1,
- "expire_at": "2021-04-23 23:59:59"
+ "expire_at": "2021-06-10 23:59:59"
+ },
+ {
+ "url": "https://www.bilibili.com/blackboard/activity-oGiWFe0YTz.html",
+ "title": "京东超市超有young",
+ "description": "活动期间每天分享页面,新增一次机会。",
+ "sid": "4eb728e2-a0d7-11eb-8597-246e966235d8",
+ "login": "true",
+ "follow": "false",
+ "share": "true",
+ "draw_times": 1,
+ "expire_at": "2021-04-25 23:59:59"
}
]
}
\ No newline at end of file
diff --git a/data/capsule_infos.json b/data/capsule_infos.json
index fff65fb..09fcb31 100644
--- a/data/capsule_infos.json
+++ b/data/capsule_infos.json
@@ -34,23 +34,23 @@
"parent_area_id": 6,
"coin_id": 121,
"watch_time": 3720,
- "draw_times": 9,
+ "draw_times": 2,
"expire_at": "2021-04-26 23:59:59"
},
{
"url": "https://live.bilibili.com/11218604",
- "title": "PGI全球邀请赛",
- "description": "每日在PGI直播间观看,10分钟1张",
+ "title": "2021PCL春季赛观赛任务",
+ "description": "每日在PGI直播间观看,10、15、30",
"room_id": 11218604,
"area_id": 0,
"parent_area_id": 2,
- "coin_id": 91,
+ "coin_id": 129,
"watch_time": 3720,
- "draw_times": 6,
- "expire_at": "2021-03-28 23:59:59"
+ "draw_times": 3,
+ "expire_at": "2021-05-31 23:59:59"
},
{
- "url": "https://live.bilibili.com/blackboard/2021-lpl-main.html",
+ "url": "https://live.bilibili.com/6",
"title": "2021LPL春季赛",
"description": "每日在LOL直播间观看,5分钟1张,15分钟1张",
"room_id": 7734200,
@@ -59,19 +59,19 @@
"coin_id": 76,
"watch_time": 3720,
"draw_times": 3,
- "expire_at": "2021-03-28 23:59:59"
+ "expire_at": "2021-05-31 23:59:59"
},
{
"url": "https://live.bilibili.com/23",
- "title": "PEL和平精英职业联赛",
+ "title": "PEI亚洲邀请赛",
"description": "每日在PEL直播间观看,5分钟1张",
"room_id": 13242892,
"area_id": 0,
"parent_area_id": 2,
"coin_id": 109,
"watch_time": 3720,
- "draw_times": 6,
- "expire_at": "2021-04-11 23:59:59"
+ "draw_times": 2,
+ "expire_at": "2021-05-31 23:59:59"
}
]
}
\ No newline at end of file
diff --git a/data/filter_words.json b/data/filter_words.json
index bbe3b69..b5eb8ec 100644
--- a/data/filter_words.json
+++ b/data/filter_words.json
@@ -198,7 +198,106 @@
"1元红包",
"红包3.3元",
"5.2元红包",
- "2.33元红包"
+ "2.33元红包",
+ "测试",
+ "钓鱼",
+ "炸鱼",
+ "黑屋",
+ "脚本",
+ "空气",
+ "大航海",
+ "上船",
+ "舰长",
+ "返现",
+ "抵用",
+ "代金",
+ "上车",
+ "上反船",
+ "照片",
+ "素颜",
+ "自拍",
+ "皂片",
+ "开舰",
+ "上舰",
+ "自画像",
+ "封面",
+ "取关",
+ "美照",
+ "随机照",
+ "女装照",
+ "日常照",
+ "好友",
+ "给主播",
+ "照骗",
+ "连麦",
+ "情书",
+ "一局",
+ "舰涨优惠卷",
+ "开黑",
+ "test",
+ "Test",
+ "金币",
+ "元宝",
+ "代打",
+ "上分",
+ "上段",
+ "台历",
+ "一毛",
+ "五毛",
+ "王者荣耀",
+ "玩游戏",
+ "encrypt",
+ "壁纸",
+ "相片",
+ "排位",
+ "语音",
+ "车位",
+ "网剧",
+ "一起玩",
+ "一次",
+ "专属头衔",
+ "手游",
+ "宠物",
+ "蒸汽",
+ "月饼",
+ "加速",
+ "挂件",
+ "渔夫",
+ "小黑屋",
+ "头像",
+ "许愿码",
+ "电池",
+ "赛车",
+ "保底",
+ "代币",
+ "越南盾",
+ "网点",
+ "机器",
+ "话梅",
+ "志愿",
+ "令牌",
+ "永久",
+ "第五人格",
+ "大蒜",
+ "唢呐",
+ "皇冠",
+ "徽章",
+ "铜牌",
+ "动物园",
+ "植物",
+ "钻石",
+ "宝石",
+ "尖叫",
+ "扭蛋机",
+ "点播",
+ "数字版月历",
+ "点歌一首",
+ "体验",
+ "点歌",
+ "三次取关",
+ "大航海",
+ "3块钱之前的巨款",
+ "礼金"
]
},
"CapsuleLottery": {
diff --git a/src/core/Env.php b/src/core/Env.php
index 49ab0a7..6015082 100644
--- a/src/core/Env.php
+++ b/src/core/Env.php
@@ -13,7 +13,7 @@ namespace BiliHelper\Core;
class Env
{
private $app_name = 'BiliHelper Personal';
- private $app_version = '0.8.0.*';
+ private $app_version = '0.8.1.*';
/**
* Env constructor.
diff --git a/src/plugin/CapsuleLottery.php b/src/plugin/CapsuleLottery.php
index 382d30a..bcdcc81 100644
--- a/src/plugin/CapsuleLottery.php
+++ b/src/plugin/CapsuleLottery.php
@@ -15,53 +15,37 @@ use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\AllotTasks;
use BiliHelper\Util\TimeLock;
-use BiliHelper\Tool\Generator;
+use BiliHelper\Util\XliveHeartBeat;
class CapsuleLottery
{
use TimeLock;
use AllotTasks;
+ use XliveHeartBeat;
private static $repository = APP_DATA_PATH . 'capsule_infos.json';
-
- private static $work_room_id = null;
- private static $enc_server = null; // 加密服务器 配置文件
- private static $hb_payload = []; // 心跳请求数据
- private static $hb_headers = []; // 心跳请求头
- private static $hb_count_total = 0;
- private static $hb_count = 0; // 心跳次数 max 24
- private static $hb_room_info = []; // 心跳带勋章房间信息
- private static $heartbeat_interval = 60; // 每次跳动时间
+ private static $interval = 60;
+ /**
+ * @throws \JsonDecodeStream\Exception\TokenizerException
+ * @throws \JsonDecodeStream\Exception\SelectorException
+ * @throws \JsonDecodeStream\Exception\ParserException
+ * @throws \JsonDecodeStream\Exception\CollectorException
+ */
public static function run()
{
- if (self::getLock() > time() || !self::init()) {
+ if (self::getLock() > time() || getenv('USE_CAPSULE') == 'false') {
return;
}
self::allotTasks();
if (self::workTask()) {
- self::setLock(self::$heartbeat_interval);
+ self::setLock(self::$interval);
} else {
self::setLock(self::timing(5) + mt_rand(1, 180));
}
}
- /**
- * @use init
- * @return bool
- */
- private static function init(): bool
- {
- if (getenv('USE_CAPSULE') == 'false' || getenv('ENC_SERVER') == '') {
- return false;
- }
- if (is_null(self::$enc_server)) {
- self::$enc_server = getenv('ENC_SERVER');
- }
- return true;
- }
-
/**
* @use 分配任务
@@ -126,7 +110,8 @@ class CapsuleLottery
// 执行任务
switch ($task['operation']) {
case 'watch':
- self::heartBeat($task['act']->room_id);
+ $interval = self::xliveHeartBeatTask($task['act']->room_id,999,999);
+ self::$interval = $interval == 0 ? 60 : $interval;
break;
case 'draw':
self::doLottery($task['act']->coin_id, $task['act']->url, 0);
@@ -138,196 +123,6 @@ class CapsuleLottery
return true;
}
-
- /**
- * @use 重置变量
- * @param false $reset_num
- */
- private static function resetVar($reset_num = false)
- {
- self::$hb_payload = []; // 心跳请求数据
- self::$hb_headers = []; // 心跳请求头
- if ($reset_num) {
- self::$hb_count_total = 0;
- }
- self::$hb_room_info = []; // 心跳带勋章房间信息
- self::$hb_count = 0; // 心跳次数 max 24
- self::$heartbeat_interval = 60; // 跳变时间
- }
-
-
- /**
- * @use 心跳处理
- * @param int $room_id
- */
- private static function heartBeat(int $room_id)
- {
- if (self::$work_room_id != $room_id) {
- self::resetVar();
- self::$work_room_id = $room_id;
- }
- if (empty(self::$hb_room_info)) {
- self::$hb_room_info = Live::webGetRoomInfo($room_id);
- }
- if (!self::$hb_count) {
- $e_data = self::eHeartBeat(self::$hb_room_info['data']['room_info']);
- if (!$e_data['status']) {
- // 错误级别
- return;
- }
- self::$hb_count += 1;
- self::$hb_count_total += 1;
- self::$hb_payload = $e_data['payload'];
- self::$hb_headers = $e_data['headers'];
- return;
- }
- $x_data = self::xHeartBeat(self::$hb_count);
- if (!$x_data['status']) {
- // 错误级别
- self::resetVar();
- return;
- }
- self::$hb_count_total += 1;
- self::$hb_count += 1;
- }
-
- /**
- * @use E心跳
- * @param array $room_info
- * @param int $index
- * @return array|bool[]
- */
- private static function eHeartBeat(array $room_info, $index = 0): array
- {
- $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/E';
- $headers = [
- 'Content-Type' => 'application/x-www-form-urlencoded',
- 'Origin' => 'https://live.bilibili.com',
- 'Referer' => 'https://live.bilibili.com/' . $room_info['room_id'],
- ];
- $user_info = User::parseCookies();
- $payload = [
- 'id' => json_encode([$room_info['parent_area_id'], $room_info['area_id'], $index, $room_info['room_id']], true),
- 'device' => json_encode([
- Generator::hash(), Generator::uuid4()
- ], true),
- 'ts' => time() * 1000,
- 'is_patch' => 0,
- 'heart_beat' => [],
- 'ua' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
- 'csrf_token' => $user_info['token'],
- 'csrf' => $user_info['token'],
- 'visit_id' => ''
- ];
- $raw = Curl::post('pc', $url, $payload, $headers);
- $de_raw = json_decode($raw, true);
- // {"code":0,"message":"0","ttl":1,"data":{"timestamp":1595342828,"heartbeat_interval":300,"secret_key":"seacasdgyijfhofiuxoannn","secret_rule":[2,5,1,4],"patch_status":2}}
- if ($de_raw['code'] != 0) {
- Log::warning("小心心礼物E-{$index}心跳失败");
- return ['status' => false];
- }
- Log::info("小心心礼物E-{$index}心跳成功");
- // Log::info($raw);
- $payload['ets'] = $de_raw['data']['timestamp'];
- $payload['secret_key'] = $de_raw['data']['secret_key'];
- $payload['heartbeat_interval'] = $de_raw['data']['heartbeat_interval'];
- $payload['secret_rule'] = $de_raw['data']['secret_rule'];
- // 自动跳变时间
- self::$heartbeat_interval = $de_raw['data']['heartbeat_interval'];
- return [
- 'status' => true,
- 'payload' => $payload,
- 'headers' => $headers,
- ];
- }
-
- /**
- * @use X心跳
- * @param int $index
- * @return array|bool[]
- */
- private static function xHeartBeat(int $index = 1): array
- {
- $s_data = self::encParamS($index);
- if (!$s_data) {
- return ['status' => false];
- }
- $s = $s_data['s'];
- $t = $s_data['payload'];
-
- $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/X';
- $user_info = User::parseCookies();
- $payload = [
- 's' => $s,
- 'id' => $t['id'],
- 'device' => $t['device'],
- 'ets' => $t['ets'],
- 'benchmark' => $t['benchmark'],
- 'time' => $t['time'],
- 'ts' => $t['ts'],
- 'ua' => $t['ua'],
- 'csrf_token' => $user_info['token'],
- 'csrf' => $user_info['token'],
- 'visit_id' => ''
- ];
- // print_r($payload);
- $raw = Curl::post('pc', $url, $payload, self::$hb_headers);
- $de_raw = json_decode($raw, true);
- # {"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":300,"timestamp":1595346846,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}}
- if ($de_raw['code'] != 0) {
- Log::warning("小心心礼物X-{$index}心跳失败");
- return ['status' => false];
- }
- self::$hb_payload['ets'] = $de_raw['data']['timestamp'];
- self::$hb_payload['secret_key'] = $de_raw['data']['secret_key'];
- self::$hb_payload['heartbeat_interval'] = $de_raw['data']['heartbeat_interval'];
- // 自动跳变时间
- self::$heartbeat_interval = $de_raw['data']['heartbeat_interval'];
- Log::info("小心心礼物X-{$index}心跳成功");
- return ['status' => true];
- }
-
- /**
- * @use 加密参数S
- * @param int $index
- * @return array|false
- */
- private static function encParamS(int $index)
- {
- // 转换index
- $temp = json_decode(self::$hb_payload['id'], true);
- $temp[2] += 1;
- self::$hb_payload['id'] = json_encode($temp, true);
- // 加密部分
- $payload = [
- 't' => [
- 'id' => self::$hb_payload['id'],
- 'device' => self::$hb_payload['device'],
- 'ets' => self::$hb_payload['ets'],
- 'benchmark' => self::$hb_payload['secret_key'],
- 'time' => self::$hb_payload['heartbeat_interval'],
- 'ts' => time() * 1000,
- 'ua' => self::$hb_payload['ua']
- ],
- 'r' => self::$hb_payload['secret_rule']
- ];
- $headers = [
- 'Content-Type' => 'application/json',
- ];
- $data = Curl::put('other', self::$enc_server, $payload, $headers);
- $de_raw = json_decode($data, true);
- if ($de_raw['code'] == 0) {
- Log::info("S加密成功 {$de_raw['s']}");
- return [
- 's' => $de_raw['s'],
- 'payload' => $payload['t']
- ];
- } else {
- Log::warning("S加密成功 {$de_raw['message']}");
- return false;
- }
- }
-
/**
* @use 开始抽奖
* @param int $coin_id
@@ -335,7 +130,7 @@ class CapsuleLottery
* @param int $num
* @return bool
*/
- private static function doLottery(int $coin_id, string $referer, int $num)
+ private static function doLottery(int $coin_id, string $referer, int $num): bool
{
$url = 'https://api.live.bilibili.com/xlive/web-ucenter/v1/capsule/open_capsule_by_id';
$headers = [
diff --git a/src/plugin/Live.php b/src/plugin/Live.php
index 5fe239d..5f3300e 100644
--- a/src/plugin/Live.php
+++ b/src/plugin/Live.php
@@ -390,7 +390,7 @@ class Live
'platform' => 'web',
'parent_area_id' => $parent_area_id,
'area_id' => $area_id,
- 'sort_type' => 'sort_type_282',
+ 'sort_type' => 'online',
'page' => $page
];
$raw = Curl::get('other', $url, $payload);
diff --git a/src/plugin/SmallHeart.php b/src/plugin/SmallHeart.php
index 03ec0ab..c2bd793 100644
--- a/src/plugin/SmallHeart.php
+++ b/src/plugin/SmallHeart.php
@@ -11,34 +11,24 @@
namespace BiliHelper\Plugin;
-use BiliHelper\Core\Log;
-use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
-use BiliHelper\Tool\Generator;
+use BiliHelper\Util\XliveHeartBeat;
class SmallHeart
{
use TimeLock;
+ use XliveHeartBeat;
- private static $enc_server = null; // 加密服务器 配置文件
-
- private static $hb_payload = []; // 心跳请求数据
- private static $hb_headers = []; // 心跳请求头
-
- private static $hb_count_total = 0;
- private static $hb_count = 0; // 心跳次数 max 24
- private static $hb_room_info = []; // 心跳带勋章房间信息
private static $fans_medals = []; // 全部勋章
private static $grey_fans_medals = []; // 灰色勋章
-
private static $metal_lock = 0; // 勋章时间锁
-
- private static $heartbeat_interval = 60; // 每次跳动时间
+ private static $interval = 60; // 每次跳动时间
+ private static $total_time = 0;
public static function run()
{
- if (!self::init()) {
+ if (getenv('USE_HEARTBEAT') == 'false') {
return;
}
@@ -48,48 +38,16 @@ class SmallHeart
}
if (self::getLock() < time()) {
self::heartBeat();
- if (self::$hb_count_total >= 200) {
- self::resetVar(true);
+ if (self::$total_time >= 12000) {
+ self::$total_time = 0;
self::setLock(self::timing(2));
} else {
- self::setLock(self::$heartbeat_interval);
+ self::setLock(self::$interval);
}
}
}
- /**
- * @use 重置变量
- * @param false $reset_num
- */
- private static function resetVar($reset_num = false)
- {
- self::$hb_payload = []; // 心跳请求数据
- self::$hb_headers = []; // 心跳请求头
- if ($reset_num) {
- self::$hb_count_total = 0;
- }
- self::$hb_room_info = []; // 心跳带勋章房间信息
- self::$hb_count = 0; // 心跳次数 max 24
- self::$heartbeat_interval = 60; // 跳变时间
- }
-
- /**
- * @use init
- * @return bool
- */
- private static function init(): bool
- {
- if (getenv('USE_HEARTBEAT') == 'false' || getenv('ENC_SERVER') == '') {
- return false;
- }
- if (is_null(self::$enc_server)) {
- self::$enc_server = getenv('ENC_SERVER');
- }
- return true;
- }
-
-
/**
* @use 勋章处理
*/
@@ -115,8 +73,6 @@ class SmallHeart
Live::sendGift($grey_fans_medal, $gift, 1);
}
}
-
-
}
@@ -128,168 +84,12 @@ class SmallHeart
if (empty(self::$fans_medals)) {
return;
}
- if (empty(self::$hb_room_info)) {
- $metal = self::$fans_medals[array_rand(self::$fans_medals)];
- self::$hb_room_info = Live::webGetRoomInfo($metal['roomid']);
- }
- if (self::$hb_count == 0) {
- $e_data = self::eHeartBeat(self::$hb_room_info['data']['room_info']);
- if (!$e_data['status']) {
- // 错误级别
- return;
- }
- self::$hb_count += 1;
- self::$hb_count_total +=1;
- self::$hb_payload = $e_data['payload'];
- self::$hb_headers = $e_data['headers'];
- return;
- }
- $x_data = self::xHeartBeat(self::$hb_count);
- if (!$x_data['status']) {
- // 错误级别
- self::resetVar();
- return;
- }
- self::$hb_count_total +=1;
- self::$hb_count += 1;
- }
-
- /**
- * @use E心跳
- * @param array $room_info
- * @param int $index
- * @return array|bool[]
- */
- private static function eHeartBeat(array $room_info, $index = 0): array
- {
- $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/E';
- $headers = [
- 'Content-Type' => 'application/x-www-form-urlencoded',
- 'Origin' => 'https://live.bilibili.com',
- 'Referer' => 'https://live.bilibili.com/' . $room_info['room_id'],
- ];
- $user_info = User::parseCookies();
- $payload = [
- 'id' => json_encode([$room_info['parent_area_id'], $room_info['area_id'], $index, $room_info['room_id']], true),
- 'device' => json_encode([
- Generator::hash(), Generator::uuid4()
- ], true),
- 'ts' => time() * 1000,
- 'is_patch' => 0,
- 'heart_beat' => [],
- 'ua' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
- 'csrf_token' => $user_info['token'],
- 'csrf' => $user_info['token'],
- 'visit_id' => ''
- ];
- $raw = Curl::post('pc', $url, $payload, $headers);
- $de_raw = json_decode($raw, true);
- // {"code":0,"message":"0","ttl":1,"data":{"timestamp":1595342828,"heartbeat_interval":300,"secret_key":"seacasdgyijfhofiuxoannn","secret_rule":[2,5,1,4],"patch_status":2}}
- if ($de_raw['code'] != 0) {
- Log::warning("小心心礼物E-{$index}心跳失败");
- return ['status' => false];
- }
- Log::info("小心心礼物E-{$index}心跳成功");
- // Log::info($raw);
- $payload['ets'] = $de_raw['data']['timestamp'];
- $payload['secret_key'] = $de_raw['data']['secret_key'];
- $payload['heartbeat_interval'] = $de_raw['data']['heartbeat_interval'];
- $payload['secret_rule'] = $de_raw['data']['secret_rule'];
- // 自动跳变时间
- self::$heartbeat_interval = $de_raw['data']['heartbeat_interval'];
- return [
- 'status' => true,
- 'payload' => $payload,
- 'headers' => $headers,
- ];
- }
-
- /**
- * @use X心跳
- * @param int $index
- * @return array|bool[]
- */
- private static function xHeartBeat(int $index = 1): array
- {
- $s_data = self::encParamS($index);
- if (!$s_data) {
- return ['status' => false];
- }
- $s = $s_data['s'];
- $t = $s_data['payload'];
-
- $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/X';
- $user_info = User::parseCookies();
- $payload = [
- 's' => $s,
- 'id' => $t['id'],
- 'device' => $t['device'],
- 'ets' => $t['ets'],
- 'benchmark' => $t['benchmark'],
- 'time' => $t['time'],
- 'ts' => $t['ts'],
- 'ua' => $t['ua'],
- 'csrf_token' => $user_info['token'],
- 'csrf' => $user_info['token'],
- 'visit_id' => ''
- ];
- // print_r($payload);
- $raw = Curl::post('pc', $url, $payload, self::$hb_headers);
- $de_raw = json_decode($raw, true);
- # {"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":300,"timestamp":1595346846,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}}
- if ($de_raw['code'] != 0) {
- Log::warning("小心心礼物X-{$index}心跳失败");
- return ['status' => false];
- }
- self::$hb_payload['ets'] = $de_raw['data']['timestamp'];
- self::$hb_payload['secret_key'] = $de_raw['data']['secret_key'];
- self::$hb_payload['heartbeat_interval'] = $de_raw['data']['heartbeat_interval'];
- // 自动跳变时间
- self::$heartbeat_interval = $de_raw['data']['heartbeat_interval'];
- Log::info("小心心礼物X-{$index}心跳成功");
- return ['status' => true];
- }
-
-
- /**
- * @use 加密参数S
- * @param int $index
- * @return array|false
- */
- private static function encParamS(int $index)
- {
- // 转换index
- $temp = json_decode(self::$hb_payload['id'], true);
- $temp[2] += 1;
- self::$hb_payload['id'] = json_encode($temp, true);
- // 加密部分
- $payload = [
- 't' => [
- 'id' => self::$hb_payload['id'],
- 'device' => self::$hb_payload['device'],
- 'ets' => self::$hb_payload['ets'],
- 'benchmark' => self::$hb_payload['secret_key'],
- 'time' => self::$hb_payload['heartbeat_interval'],
- 'ts' => time() * 1000,
- 'ua' => self::$hb_payload['ua']
- ],
- 'r' => self::$hb_payload['secret_rule']
- ];
- $headers = [
- 'Content-Type' => 'application/json',
- ];
- $data = Curl::put('other', self::$enc_server, $payload, $headers);
- $de_raw = json_decode($data, true);
- if ($de_raw['code'] == 0) {
- Log::info("S加密成功 {$de_raw['s']}");
- return [
- 's' => $de_raw['s'],
- 'payload' => $payload['t']
- ];
- } else {
- Log::warning("S加密成功 {$de_raw['message']}");
- return false;
+ $metal = self::$fans_medals[array_rand(self::$fans_medals)];
+ $interval = self::xliveHeartBeatTask($metal['roomid'], 999, 999);
+ if ($interval != 0) {
+ self::$total_time += $interval;
}
+ self::$interval = $interval == 0 ? 60 : $interval;
}
diff --git a/src/util/XliveHeartBeat.php b/src/util/XliveHeartBeat.php
new file mode 100644
index 0000000..3792a8b
--- /dev/null
+++ b/src/util/XliveHeartBeat.php
@@ -0,0 +1,243 @@
+ []]; // 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 $_retry = 3; // 重试次数
+ protected static $_count_num = 0; // 计数
+ protected static $_count_time = 0; // 计时间
+
+ protected static $_current_room_id = 0; // 当前运行的ROOM_ID
+ protected static $_enc_server = null; // 加密服务器 依赖配置文件
+
+ protected static $_default = 0; // 默认值
+
+
+ /**
+ * @use 重置变量
+ * @param false $force
+ */
+ protected static function resetVar($force = false)
+ {
+ if ($force){
+ self::$_room_info = [];
+ self::$_current_room_id = 0;
+
+ self::$_retry = 3;
+ self::$_count_num = 0;
+ self::$_count_time = 0;
+ }
+ $data = [
+ 'id' => self::$_data['id'],
+ ];
+ $data["id"][2] = 0;
+ self::$_data = $data;
+ }
+
+
+ protected static function xliveHeartBeatTask(int $room_id, int $max_time, int $max_num)
+ {
+ // 加载依赖
+ if (!self::depend()) {
+ return self::$_default;
+ }
+ // 对比当前运行
+ if (self::$_current_room_id != $room_id) {
+ self::resetVar(true);
+ self::$_current_room_id = $room_id;
+ }
+ // 加载房间信息
+ if (empty(self::$_room_info)) {
+ $r_data = Live::webGetRoomInfo($room_id);
+ if ($r_data['code'] != 0) {
+ Log::warning('直播间信息获取失败');
+ return self::$_default;
+ }
+ $rdata = $r_data['data'];
+ $parent_area_id = $rdata['room_info']['parent_area_id'];
+ $area_id = $rdata['room_info']['area_id'];
+ # 短位转长位
+ $room_id = $rdata['room_info']['room_id'];
+ self::$_data['id'] = [$parent_area_id, $area_id, 0, $room_id];
+ }
+ // 执行心跳
+ $r_data = self::heartBeatIterator();
+ $index = self::$_data['id'][2];
+ if ($r_data['code'] != 0) {
+ if (self::$_retry) {
+ Log::warning("心跳失败-{$index} {$r_data['message']}");
+ self::resetVar();
+ self::$_retry -= 1;
+ return self::$_default;
+ }
+ }
+ self::$_count_num += 1;
+ self::$_count_time += $r_data['heartbeat_interval'];
+
+ // 最大次数限制
+ if ($max_num <= self::$_count_num) {
+ // 成功在id为{room_id}的直播间发送完{ii}次心跳,退出直播心跳(达到最大心跳次数)
+ }
+ // 最大时间限制
+ if ($max_time <= self::$_count_time) {
+ //成功在id为{room_id}的直播间发送第{ii}次心跳
+ }
+ $minute = round(self::$_count_time / 60);
+ Log::info("已在直播间 {$room_id} 连续观看了 {$minute} 分钟");
+ return $r_data['heartbeat_interval'];
+
+ }
+
+ /**
+ * @use 检查依赖
+ * @return bool
+ */
+ protected static function depend(): bool
+ {
+ if (getenv('ENC_SERVER') == '') {
+ return false;
+ }
+ // 加载加密服务器
+ if (is_null(self::$_enc_server)) {
+ self::$_enc_server = getenv('ENC_SERVER');
+ }
+ return true;
+ }
+
+
+ protected static function heartBeatIterator(): array
+ {
+ $rdata = [];
+ # 第1次执行 eHeartBeat
+ if (self::$_data['id'][2] == 0) {
+ $r_data = self::eHeartBeat(self::$_data['id']);
+ } else {
+ # 第1次之后执行 xHeartBeat
+ self::$_data['ts'] = time() * 1000;
+ self::$_data['s'] = self::encParamS(self::$_data, self::$_secret_rule);
+ $r_data = self::xHeartBeat(self::$_data['id']);
+ }
+ if ($r_data['code'] == 0) {
+ $rdata = $r_data['data'];
+ self::$_data['ets'] = $rdata['timestamp'];
+ self::$_data['benchmark'] = $rdata['secret_key'];
+ self::$_data['time'] = $rdata['heartbeat_interval'];
+ self::$_secret_rule = $rdata['secret_rule'];
+ self::$_data['id'][2] += 1;
+ }
+ return [
+ 'code' => $r_data['code'],
+ 'message' => $r_data['message'],
+ 'heartbeat_interval' => $rdata['heartbeat_interval']
+ ];
+ }
+
+
+ /**
+ * @use E心跳
+ * @param array $id
+ * @return array|false[]
+ */
+ protected static function eHeartBeat(array $id): array
+ {
+ $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/E';
+ $headers = [
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ 'Origin' => 'https://live.bilibili.com',
+ 'Referer' => 'https://live.bilibili.com/' . $id[3],
+ ];
+ $user_info = User::parseCookies();
+ $payload = [
+ 'id' => json_encode([$id[0], $id[1], $id[2], $id[3]], true),
+ 'device' => json_encode([Generator::hash(), Generator::uuid4()], true),
+ 'ts' => time() * 1000,
+ 'is_patch' => 0,
+ 'heart_beat' => [],
+ 'ua' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
+ 'csrf_token' => $user_info['token'],
+ 'csrf' => $user_info['token'],
+ 'visit_id' => ''
+ ];
+ $raw = Curl::post('pc', $url, $payload, $headers);
+ // {'code':0,'message':'0','ttl':1,'data':{'timestamp':1595342828,'heartbeat_interval':300,'secret_key':'seacasdgyijfhofiuxoannn','secret_rule':[2,5,1,4],'patch_status':2}}
+
+ unset($payload['id']);
+ self::$_data = array_merge_recursive(self::$_data, $payload);
+
+ return json_decode($raw, true);
+ }
+
+ /**
+ * @use X心跳
+ * @param array $id
+ * @return array|bool[]
+ */
+ protected static function xHeartBeat(array $id): array
+ {
+ $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/X';
+ $user_info = User::parseCookies();
+ $payload = [
+ 's' => self::$_data['s'],
+ 'id' => json_encode([$id[0], $id[1], $id[2], $id[3]], true),
+ 'device' => self::$_data['device'],
+ 'ets' => self::$_data['ets'],
+ 'benchmark' => self::$_data['benchmark'],
+ 'time' => self::$_data['time'],
+ 'ts' => self::$_data['ts'],
+ 'ua' => self::$_data['ua'],
+ 'csrf_token' => $user_info['token'],
+ 'csrf' => $user_info['token'],
+ 'visit_id' => ''
+ ];
+ // print_r($payload);
+ $raw = Curl::post('pc', $url, $payload, self::$hb_headers);
+ # {'code':0,'message':'0','ttl':1,'data':{'heartbeat_interval':300,'timestamp':1595346846,'secret_rule':[2,5,1,4],'secret_key':'seacasdgyijfhofiuxoannn'}}
+ return json_decode($raw, true);
+ }
+
+ /**
+ * @use 加密参数S
+ * @param array $t
+ * @param array $r
+ * @return string|false
+ */
+ protected static function encParamS(array $t, array $r)
+ {
+ $headers = [
+ 'Content-Type' => 'application/json',
+ ];
+ // 加密部分
+ $payload = ['t' => $t, 'r' => $r];
+ $data = Curl::put('other', self::$_enc_server, $payload, $headers);
+ $de_raw = json_decode($data, true);
+ if ($de_raw['code'] == 0) {
+ // Log::info("S加密成功 {$de_raw['s']}");
+ return $de_raw['s'];
+ } else {
+ Log::warning("S加密失败 {$de_raw['message']}");
+ return false;
+ }
+ }
+
+
+}
\ No newline at end of file