[update] Version 0.5.0

This commit is contained in:
Lkeme 2020-06-24 19:21:00 +08:00
parent ca9fadf7a5
commit dbee2e2f6a
33 changed files with 1182 additions and 174 deletions

View File

@ -1,6 +1,33 @@
# Release Notes
# 本项目Log
## v0.5.0.200624 alpha (2020-06-24)
### Added
- 添加破产机(赔到破产)
- 添加推送KEY到期通知
- 添加天选自动取关(测试)
- 添加收益统计
- 添加关注投币模式
-
### Changed
- 更新部分信息输出
- 修改日志打印前缀
- 更新活跃弹幕延迟
- 重构部分统计代码
- 更新视频投币逻辑
- 更新实物抽奖API
- 修改硬币兑换延迟
-
### Fixed
- 修复日志输出错误
- 修复每日送礼异常
- 修复赛事逻辑错误
- 修复部分已知问题
-
## v0.4.0.200505 alpha (2020-05-05)
### Added

53
DOC.md
View File

@ -2,7 +2,7 @@
<p align="center"><img width="300px" src="https://i.loli.net/2018/04/20/5ad97bd395912.jpeg"></p>
<p align="center">
<img src="https://img.shields.io/badge/version-0.4.0.200505 alpha-green.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/version-0.5.0.200624 alpha-green.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/license-mit-blue.svg?longCache=true&style=for-the-badge">
</p>
@ -15,31 +15,32 @@ B 站直播实用脚本
|plugin |version |description |
|--------------------|--------------------|--------------------|
|Login |20.05.05 |账号登录 |
|Schedule |20.05.05 |休眠控制 |
|MasterSite |20.05.05 |主站助手 |
|Daily |20.05.05 |每日礼包 |
|Heart |20.05.05 |双端心跳 |
|Task |20.05.05 |每日任务 |
|Silver |20.05.05 |银瓜子宝箱 |
|Barrage |20.05.05 |活跃弹幕 |
|Silver2Coin |20.05.05 |银瓜子换硬币 |
|GiftSend |20.05.05 |礼物赠送 |
|Judge |20.05.05 |风纪 |
|GroupSignIn |20.05.05 |友爱社签到 |
|ManGa |20.05.05 |漫画签到分享 |
|Match |20.05.05 |赛事签到分享 |
|GiftHeart |20.05.05 |心跳礼物 |
|MaterialObject |20.05.05 |实物抽奖 |
|AloneTcpClient |20.05.05 |独立监控 |
|ZoneTcpClient |20.05.05 |分区监控 |
|StormRaffle |20.05.05 |节奏风暴 |
|GiftRaffle |20.05.05 |活动礼物 |
|PkRaffle |20.05.05 |大乱斗 |
|GuardRaffle |20.05.05 |舰长总督 |
|AnchorRaffle |20.05.05 |天选时刻 |
|AwardRecord |20.05.05 |获奖通知 |
|Statistics |20.05.05 |数据统计 |
|Login |20.06.24 |账号登录 |
|Schedule |20.06.24 |休眠控制 |
|MasterSite |20.06.24 |主站助手 |
|Daily |20.06.24 |每日礼包 |
|Heart |20.06.24 |双端心跳 |
|Task |20.06.24 |每日任务 |
|Silver |20.06.24 |银瓜子宝箱 |
|Barrage |20.06.24 |活跃弹幕 |
|Silver2Coin |20.06.24 |银瓜子换硬币 |
|GiftSend |20.06.24 |礼物赠送 |
|Judge |20.06.24 |风纪 |
|GroupSignIn |20.06.24 |友爱社签到 |
|ManGa |20.06.24 |漫画签到分享 |
|Match |20.06.24 |赛事签到分享 |
|GiftHeart |20.06.24 |心跳礼物 |
|MaterialObject |20.06.24 |实物抽奖 |
|AloneTcpClient |20.06.24 |独立监控 |
|ZoneTcpClient |20.06.24 |分区监控 |
|StormRaffle |20.06.24 |节奏风暴 |
|GiftRaffle |20.06.24 |活动礼物 |
|PkRaffle |20.06.24 |大乱斗 |
|GuardRaffle |20.06.24 |舰长总督 |
|AnchorRaffle |20.06.24 |天选时刻 |
|AwardRecord |20.06.24 |获奖通知 |
|Statistics |20.06.24 |数据统计 |
|Competition |20.06.24 |赛事竞猜 |
## 打赏赞助

View File

@ -7,7 +7,7 @@ Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg) | **仅用于BUG提交
## 公告
> Currently for Personal Edition **0.4.0.200505 alpha**
> Currently for Personal Edition **0.5.0.200624 alpha**
```notice
---- 免费的东西总是得不到人的珍惜。

View File

@ -15,7 +15,8 @@
"clue/socket-raw": "^1.4.1",
"vlucas/phpdotenv": "^4.1",
"amphp/amp": "^2.4",
"guzzlehttp/guzzle": "^6.5"
"guzzlehttp/guzzle": "^6.5",
"mathieuviossat/arraytotexttable": "^1.0"
},
"license": "MIT",
"authors": [

331
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "e12b1349c43efa1aa58a89b33a44613e",
"content-hash": "773a1bbd829be3a7bb684f926002ac37",
"packages": [
{
"name": "amphp/amp",
@ -245,6 +245,44 @@
],
"time": "2019-10-28T12:32:07+00:00"
},
{
"name": "container-interop/container-interop",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/container-interop/container-interop.git",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"psr/container": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Interop\\Container\\": "src/Interop/Container/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"homepage": "https://github.com/container-interop/container-interop",
"abandoned": "psr/container",
"time": "2017-02-14T19:40:03+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.5.3",
@ -452,6 +490,59 @@
],
"time": "2019-07-01T23:21:34+00:00"
},
{
"name": "mathieuviossat/arraytotexttable",
"version": "v1.0.7",
"source": {
"type": "git",
"url": "https://github.com/viossat/arraytotexttable.git",
"reference": "df25fafc56cedd64fcdab5a1d8793d0e97e635e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/viossat/arraytotexttable/zipball/df25fafc56cedd64fcdab5a1d8793d0e97e635e3",
"reference": "df25fafc56cedd64fcdab5a1d8793d0e97e635e3",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3.0",
"zendframework/zend-text": "^2.0.3"
},
"type": "library",
"autoload": {
"psr-4": {
"MathieuViossat\\Util\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mathieu Viossat",
"email": "mathieu@viossat.fr",
"homepage": "https://viossat.fr"
}
],
"description": "Display arrays in terminal",
"homepage": "https://github.com/viossat/arraytotexttable",
"keywords": [
"array",
"ascii",
"table",
"terminal",
"text",
"unicode"
],
"time": "2019-05-15T14:51:03+00:00"
},
{
"name": "monolog/monolog",
"version": "1.25.3",
@ -597,6 +688,61 @@
],
"time": "2020-03-21T18:07:53+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
@ -1145,6 +1291,189 @@
}
],
"time": "2020-04-12T15:20:09+00:00"
},
{
"name": "zendframework/zend-servicemanager",
"version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-servicemanager.git",
"reference": "a1ed6140d0d3ee803fec96582593ed024950067b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/a1ed6140d0d3ee803fec96582593ed024950067b",
"reference": "a1ed6140d0d3ee803fec96582593ed024950067b",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"container-interop/container-interop": "^1.2",
"php": "^5.6 || ^7.0",
"psr/container": "^1.0",
"zendframework/zend-stdlib": "^3.2.1"
},
"provide": {
"container-interop/container-interop-implementation": "^1.2",
"psr/container-implementation": "^1.0"
},
"require-dev": {
"mikey179/vfsstream": "^1.6.5",
"ocramius/proxy-manager": "^1.0 || ^2.0",
"phpbench/phpbench": "^0.13.0",
"phpunit/phpunit": "^5.7.25 || ^6.4.4",
"zendframework/zend-coding-standard": "~1.0.0"
},
"suggest": {
"ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services",
"zendframework/zend-stdlib": "zend-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances"
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.3-dev",
"dev-develop": "4.0-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"keywords": [
"PSR-11",
"ZendFramework",
"dependency-injection",
"di",
"dic",
"service-manager",
"servicemanager",
"zf"
],
"abandoned": "laminas/laminas-servicemanager",
"time": "2018-12-22T06:05:09+00:00"
},
{
"name": "zendframework/zend-stdlib",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-stdlib.git",
"reference": "66536006722aff9e62d1b331025089b7ec71c065"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/66536006722aff9e62d1b331025089b7ec71c065",
"reference": "66536006722aff9e62d1b331025089b7ec71c065",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpbench/phpbench": "^0.13",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2",
"zendframework/zend-coding-standard": "~1.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"keywords": [
"ZendFramework",
"stdlib",
"zf"
],
"abandoned": "laminas/laminas-stdlib",
"time": "2018-08-28T21:34:05+00:00"
},
{
"name": "zendframework/zend-text",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-text.git",
"reference": "41e32dafa4015e160e2f95a7039554385c71624d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-text/zipball/41e32dafa4015e160e2f95a7039554385c71624d",
"reference": "41e32dafa4015e160e2f95a7039554385c71624d",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
"zendframework/zend-stdlib": "^2.7 || ^3.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4",
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-config": "^2.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7.x-dev",
"dev-develop": "2.8.x-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Text\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create FIGlets and text-based tables",
"keywords": [
"ZendFramework",
"text",
"zf"
],
"abandoned": "laminas/laminas-text",
"time": "2019-10-16T20:36:27+00:00"
}
],
"packages-dev": [],

View File

@ -27,8 +27,9 @@ USE_GUARD=true
# 大乱斗
USE_PK=true
# 天选时刻|抽取类型(0: 无限制; 1: 关注主播; 2: 粉丝勋章; 3大航海 4用户等级5主站等级)|过滤关键词|逗号分隔
# 天选时刻|抽取类型(0: 无限制; 1: 关注主播; 2: 粉丝勋章; 3大航海 4用户等级5主站等级)|自动取关(测试功能)|过滤关键词|逗号分隔
USE_ANCHOR=false
ANCHOR_UNFOLLOW=false
ANCHOR_TYPE=0,1
ANCHOR_FILTER_WORDS=
@ -48,10 +49,10 @@ USE_DANMU=true
DANMU_ROOMID=9522051
DANMU_CONTENT=
# 视频投币|投币稿件数(每日任务最大5)|自定义稿件ID,空则随机(AV_NUM=1生效)
# 视频投币|random(随机热门)/fixed(关注列表)|投币稿件数(每日任务最大5)
USE_ADD_COIN=false
ADD_COIN_AV_NUM=1
ADD_COIN_AV=33492180
ADD_COIN_MODE=random
ADD_COIN_NUM=5
# 休眠时间|时间区间(0-23)|逗号分隔
USE_SLEEP=true
@ -63,7 +64,13 @@ USE_MANGA=false
# 赛事助手
USE_MATCH=false
# 风纪(测试)
# 破产机|每日竞猜次数|每次竞猜硬币(1-10)|下注(1.压大,2.压小,3.随机)
USE_COMPETITION=false
COMPET_MAX_NUM=20
COMPET_MAX_COIN=10
COMPET_STAKE=1
# 风纪委员
USE_JUDGE=false
#######################
@ -71,8 +78,8 @@ USE_JUDGE=false
#######################
# 独立推送服务(主)|主备冲突
USE_ALONE_SERVER=false
ALONE_SERVER_ADDR=
USE_ALONE_SERVER=true
ALONE_SERVER_ADDR=tcp://livecmt-1.mudew.com:10088
ALONE_SERVER_KEY=
# 分区推送服务(备)|主备冲突

View File

@ -70,6 +70,7 @@ class App
'Daily',
'ManGa',
'Match',
'Competition',
'Heart',
'Task',
'Silver',

View File

@ -13,7 +13,7 @@ namespace BiliHelper\Core;
class Env
{
private $app_name = 'BiliHelper Personal';
private $app_version = '0.4.0.*';
private $app_version = '0.5.0.*';
/**
* Env constructor.
@ -50,7 +50,7 @@ class Env
public function inspect_configure()
{
Log::info("欢迎使用 {$this->app_name} 当前版本 {$this->app_version}");
Log::info("程序使用相关请移步 https://github.com/lkeme/BiliHelper-personal 文档部分查看。");
Log::info("使用说明请移步 https://github.com/lkeme/BiliHelper-personal 查看。");
if (PHP_SAPI != 'cli') {
die("Please run this script from command line .");

View File

@ -29,7 +29,7 @@ class Log
protected static function configureInstance()
{
$logger = new Logger('Bilibili');
$logger = new Logger('BH');
$handler = new StreamHandler('php://stdout', getenv('APP_DEBUG') == 'true' ? Logger::DEBUG : Logger::INFO);
$handler->setFormatter(new ColoredLineFormatter());
$logger->pushHandler($handler);

View File

@ -228,8 +228,12 @@ class AloneTcpClient
Log::info("确认到推送服务器 {$raw_data['type']}");
break;
case 'error':
// 致命错误
Log::error("推送服务器发生致命错误 {$raw_data['data']['msg']}");
// 产生错误
Log::error("推送服务器异常 {$raw_data['data']['msg']}, 程序挂起请手动关闭!");
// KEY到期推送提醒
Notice::push('key_expired', '');
// 程序挂起 防止systemd无限重启导致触发过多推送提醒
sleep(86400);
exit();
break;
case 'heartbeat':

View File

@ -24,8 +24,102 @@ class AnchorRaffle extends BaseRaffle
protected static $wait_list = [];
protected static $finish_list = [];
protected static $all_list = [];
// 过滤类型
private static $filter_type = [];
// 默认关注 特殊关注 等待关注
private static $default_follows = [];
private static $special_follows = [];
public static $wait_un_follows = [];
// 特殊分组 分组ID
private static $group_name = "玄不改非"; // 氪不改命
private static $group_id = null;
/**
* @use 删除分组
* @param int $un_follow_uid
* @param int $anchor_id
* @param bool $un_follow
*/
public static function delToGroup(int $un_follow_uid, int $anchor_id, bool $un_follow = true)
{
// 取关
if ($un_follow) {
User::setUserFollow($un_follow_uid, true);
}
self::delValue($un_follow_uid, $anchor_id);
}
/**
* @use 添加分组
* @param int $room_id
* @param int $anchor_id
* @param int $time
*/
private static function addToGroup(int $room_id, int $anchor_id, int $time)
{
// 获取分组id
if (is_null(self::$group_id)) {
$tags = User::fetchTags();
$tag_id = array_search(self::$group_name, $tags);
// 如果不存在则调用创建
self::$group_id = $tag_id ? $tag_id : User::createRelationTag(self::$group_name);
}
// 获取需要关注的
$data = Live::getRoomInfo($room_id);
if ($data['code'] == 0 && isset($data['data'])) {
$need_follow_uid = $data['data']['uid'];
} else {
return;
}
// 是否在关注里
$default_follows = self::getDefaultFollows();
if (!in_array($need_follow_uid, $default_follows)) {
User::setUserFollow($need_follow_uid);
User::tagAddUsers($need_follow_uid, self::$group_id);
// 添加到检测中奖
array_push(self::$wait_un_follows, [
'uid' => $need_follow_uid,
'anchor_id' => $anchor_id,
'time' => $time,
]);
}
}
/**
* @use 删除值并重置数组
* @param int $uid
* @param int $anchor_id
*/
private static function delValue(int $uid, int $anchor_id)
{
$new_list = [];
foreach (self::$wait_un_follows as $wait_un_follow) {
if ($wait_un_follow['uid'] == $uid && $wait_un_follow['uid'] == $anchor_id) {
continue;
}
array_push($new_list, $wait_un_follow);
}
self::$wait_un_follows = $new_list;
}
/**
* @use 获取默认关注
* @return array
*/
private static function getDefaultFollows(): array
{
if (!empty(self::$default_follows)) {
return self::$default_follows;
}
// 如果获取默认关注错误 或者 为空则补全一个
self::$default_follows = User::fetchTagFollowings();
if (empty(self::$default_follows)) {
array_push(self::$default_follows, 1);
}
return self::$default_follows;
}
/**
@ -88,6 +182,10 @@ class AnchorRaffle extends BaseRaffle
if (self::toRepeatLid($de_raw['id'])) {
return false;
}
// 分组操作
if (getenv('ANCHOR_UNFOLLOW') == 'true' && $de_raw['require_text'] == '关注主播') {
self::addToGroup($room_id, $de_raw['id'], time() + $de_raw['time'] + 5);
}
// 推入列表
$data = [
'room_id' => $room_id,
@ -95,7 +193,7 @@ class AnchorRaffle extends BaseRaffle
'raffle_name' => $de_raw['award_name'],
'wait' => time() + mt_rand(5, 25)
];
Statistics::addPushList(self::ACTIVE_TITLE);
Statistics::addPushList($data['raffle_name']);
array_push(self::$wait_list, $data);
return true;
}
@ -125,7 +223,8 @@ class AnchorRaffle extends BaseRaffle
'payload' => Sign::common($payload),
'source' => [
'room_id' => $raffle['room_id'],
'raffle_id' => $raffle['raffle_id']
'raffle_id' => $raffle['raffle_id'],
'raffle_name' => $raffle['raffle_name']
]
]);
}
@ -147,7 +246,7 @@ class AnchorRaffle extends BaseRaffle
$de_raw = json_decode($content, true);
// {"code":-403,"data":null,"message":"访问被拒绝","msg":"访问被拒绝"}
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
Statistics::addSuccessList(self::ACTIVE_TITLE);
Statistics::addSuccessList($data['raffle_name']);
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": 参与抽奖成功~");
} elseif (isset($de_raw['msg']) && $de_raw['code'] == -403 && $de_raw['msg'] == '访问被拒绝') {
Log::debug("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['message']}");

View File

@ -17,6 +17,7 @@ use BiliHelper\Util\TimeLock;
class AwardRecord
{
use TimeLock;
private static $raffle_lock = 0;
private static $raffle_list = [];
private static $anchor_lock = 0;
@ -75,6 +76,18 @@ class AwardRecord
}
array_push(self::$anchor_list, $anchor['id']);
}
// 处理取关操作
foreach (AnchorRaffle::$wait_un_follows as $wait_un_follow) {
if ($wait_un_follow['time'] > time()) {
continue;
}
if (in_array($wait_un_follow['anchor_id'], self::$anchor_list)) {
AnchorRaffle::delToGroup($wait_un_follow['uid'], $wait_un_follow['anchor_id'], false);
}else{
AnchorRaffle::delToGroup($wait_un_follow['uid'], $wait_un_follow['anchor_id'], true);
}
}
self::$anchor_lock = time() + 6 * 60 * 60;
}

View File

@ -33,7 +33,7 @@ class Barrage
];
if (self::privateSendMsg($info)) {
self::setLock(mt_rand(15, 30) * 60);
self::setLock(mt_rand(20, 40) * 60);
return;
}
@ -117,7 +117,7 @@ class Barrage
*/
private static function privateSendMsg($info): bool
{
//TODO 暂时性功能 有需求就修改
//TODO 短期功能 有需求就修改
$response = self::sendMsg($info);
if (isset($response['code']) && $response['code'] == 0) {
Log::info('活跃弹幕发送成功!');

View File

@ -63,7 +63,7 @@ abstract class BaseRaffle
}
array_push($room_list, $raffle['room_id']);
array_push($raffle_list, $raffle);
Statistics::addJoinList(static::ACTIVE_TITLE);
Statistics::addJoinList($raffle['raffle_name']);
}
if (count($raffle_list) && count($room_list)) {
$room_list = array_unique($room_list);
@ -90,6 +90,7 @@ abstract class BaseRaffle
$raw = Curl::get('app', $url, Sign::common($payload));
$de_raw = json_decode($raw, true);
if (!isset($de_raw['data']) || $de_raw['code']) {
// TODO 请求被拦截 412
Log::error("获取抽奖数据错误,{$de_raw['message']}");
return [];
}

172
src/plugin/Competition.php Normal file
View File

@ -0,0 +1,172 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2020 ~ 2021
*/
namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
class Competition
{
use TimeLock;
public static function run()
{
if (getenv('USE_COMPETITION') == 'false' || self::getLock() > time()) {
return;
}
self::startStake();
self::setLock(self::timing(1,30));
}
/**
* @use 开始破产
*/
private static function startStake()
{
$questions = self::fetchQuestions();
$max_guess = intval(getenv('COMPET_MAX_NUM'));
foreach ($questions as $index => $question) {
if (($index + 1) >= $max_guess) {
break;
}
// int $, int $main_id, int $detail_id, int $coin_num
$guess = self::parseQuestion($question);
self::addGuess($guess);
}
}
/**
* @use 添加竞猜
* @param array $guess
*/
private static function addGuess(array $guess)
{
Log::info($guess['title']);
Log::info($guess['estimate']);
$user_info = User::parseCookies();
$url = 'https://api.bilibili.com/x/esports/guess/add';
$payload = [
'oid' => $guess['oid'],
'main_id' => $guess['main_id'],
'detail_id' => $guess['detail_id'],
'count' => $guess['count'],
'is_fav' => 0,
'csrf' => $user_info['token']
];
$headers = [
'origin' => 'https://www.bilibili.com',
'referer' => 'https://www.bilibili.com/v/game/match/competition'
];
$raw = Curl::post('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
// {"code":0,"message":"0","ttl":1}
if ($de_raw['code'] == 0) {
Log::notice("破产成功: {$de_raw['message']}");
} else {
Log::warning("破产失败: {$raw}");
}
}
/**
* @use 预计猜测结果
* @param array $question
* @return array
*/
private static function parseQuestion(array $question): array
{
$guess = [];
$guess['oid'] = $question['contest']['id'];
$guess['main_id'] = $question['questions'][0]['id'];
$details = $question['questions'][0]['details'];
$guess['count'] = intval(in_array(getenv('COMPET_MAX_COIN'), range(1, 10)) ? getenv('COMPET_MAX_COIN') : 10);
$guess['title'] = $question['questions'][0]['title'];
foreach ($details as $detail) {
$guess['title'] .= " 队伍: {$detail['option']} 赔率: {$detail['odds']}";
}
array_multisort(array_column($details, "odds"), SORT_ASC, $details);
switch (intval(getenv('COMPET_STAKE'))) {
case 1:
// 压大
$detail = array_pop($details);
break;
case 2:
// 压小
$detail = array_shift($details);
break;
case 3:
// 随机
$detail = $details[array_rand($details)];
break;
default:
// 乱序
shuffle($details);
$detail = $details[array_rand($details)];
break;
}
$guess['detail_id'] = $detail['detail_id'];
$profit = ceil($guess['count'] * $detail['odds']);
$guess['estimate'] = "竞猜队伍: {$detail['option']} 预计下注: {$guess['count']} 预计赚取: {$profit} 预计亏损: {$guess['count']} (硬币)";
return $guess;
}
/**
* @use 获取所有问题
* @param int $page_max
* @return array
*/
private static function fetchQuestions(int $page_max = 10): array
{
$questions = [];
$url = 'https://api.bilibili.com/x/esports/guess/collection/question';
for ($i = 1; $i < $page_max; $i++) {
$payload = [
'pn' => $i,
'ps' => 50,
'stime' => date("Y-m-d H:i:s", strtotime(date("Y-m-d", time()))),
'etime' => date("Y-m-d H:i:s", strtotime(date("Y-m-d", time())) + 86400 - 1)
];
$headers = [
'origin' => 'https://www.bilibili.com',
'referer' => 'https://www.bilibili.com/v/game/match/competition',
];
$raw = Curl::get('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
if ($de_raw['code'] == 0 && isset($de_raw['data']['list'])) {
// 为空跳出
if (count($de_raw['data']['list']) == 0) {
break;
}
// 添加到集合
foreach ($de_raw['data']['list'] as $question) {
// 判断是否有效 正2分钟
if (($question['contest']['stime'] - 600 - 120) > time()) {
array_push($questions, $question);
}
}
// 和页面的不匹配 跳出
if (count($de_raw['data']['list']) != $de_raw['data']['page']['size']) {
break;
}
} else {
// 错误跳出
break;
}
}
Log::info('获取到 ' . count($questions) . ' 个有效竞猜');
return $questions;
}
}

View File

@ -53,11 +53,11 @@ class GiftRaffle extends BaseRaffle
$data = [
'room_id' => $room_id,
'raffle_id' => $gift['raffleId'],
'title' => $gift['title'],
'raffle_name' => $gift['title'],
'type' => $gift['type'],
'wait' => $gift['time_wait'] + time(),
];
Statistics::addPushList(self::ACTIVE_TITLE);
Statistics::addPushList($data['raffle_name']);
array_push(self::$wait_list, $data);
}
return true;
@ -91,7 +91,8 @@ class GiftRaffle extends BaseRaffle
'payload' => Sign::common($payload),
'source' => [
'room_id' => $raffle['room_id'],
'raffle_id' => $raffle['raffle_id']
'raffle_id' => $raffle['raffle_id'],
'raffle_name' => $raffle['raffle_name']
]
]);
}
@ -118,13 +119,14 @@ class GiftRaffle extends BaseRaffle
$info = $de_raw['data']['award_name'] . 'x' . $de_raw['data']['award_num'];
Notice::push('gift', $info);
}
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['data']['award_name']}x{$de_raw['data']['award_num']}");
Statistics::addSuccessList(self::ACTIVE_TITLE);
Statistics::addSuccessList($data['raffle_name']);
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: {$de_raw['data']['award_name']}x{$de_raw['data']['award_num']}");
Statistics::addProfitList($data['raffle_name'] . '-' . $de_raw['data']['award_name'], $de_raw['data']['award_num']);
} elseif (isset($de_raw['msg']) && $de_raw['code'] == -403 && $de_raw['msg'] == '访问被拒绝') {
Log::debug("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['msg']}");
Log::debug("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: {$de_raw['msg']}");
self::pauseLock();
} else {
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['msg']}");
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: " . isset($de_raw['msg']) ? $de_raw['msg'] : $de_raw);
}
}
}

View File

@ -43,7 +43,12 @@ class GiftSend
self::$room_list = [];
self::$medal_list = [];
self::$tid = 0;
self::setLock(5 * 60);
// 如果在每日最后5分钟内 就50s执行一次 否则 第二天固定时间执行
if (self::inTime('23:55:00', '23:59:59')) {
self::setLock(50);
} else {
self::setLock(self::timing(23, 55));
}
}
@ -136,7 +141,9 @@ class GiftSend
if (isset($data['data']['list'])) {
$bag_list = $data['data']['list'];
if (count($bag_list)) {
array_multisort(array_column($bag_list, "gift_id"), SORT_DESC, $bag_list);
// 按过期时间 升序
// array_multisort(array_column($bag_list, "gift_id"), SORT_DESC, $bag_list);
array_multisort(array_column($bag_list, "expire_at"), SORT_ASC, $bag_list);
}
foreach ($bag_list as $vo) {
// 去除永久礼物
@ -192,14 +199,14 @@ class GiftSend
$fans_medals[(string)$vo['roomid']] = $vo;
}
// 基于配置
foreach (self::$room_list as $room_id ){
foreach (self::$room_list as $room_id) {
// 配置是否存在获取
if (!array_key_exists((string)$room_id ,$fans_medals)){
if (!array_key_exists((string)$room_id, $fans_medals)) {
continue;
}
$vo = $fans_medals[(string)$room_id];
// 是否还需要投喂
if ($vo['day_limit'] - $vo['today_feed']){
if ($vo['day_limit'] - $vo['today_feed']) {
self::$medal_list[(string)$vo['roomid']] = ($vo['day_limit'] - $vo['today_feed']);
}
}

View File

@ -73,8 +73,8 @@ class GroupSignIn
$de_raw = json_decode($raw, true);
if ($de_raw['code'] != '0') {
Log::warning('在应援团{' . $groupInfo['group_name'] . '}中签到失败,原因待查');
// TODO
Log::warning('在应援团{' . $groupInfo['group_name'] . '}中签到失败, 原因待查');
// TODO 任务失败原因
return false;
}
if ($de_raw['data']['status'] == '0') {

View File

@ -53,28 +53,29 @@ class GuardRaffle extends BaseRaffle
continue;
}
// 获取等级名称
switch ($guard['privilege_type']) {
case 1:
$raffle_name = '总督';
break;
case 2:
$raffle_name = '提督';
break;
case 3:
$raffle_name = '舰长';
break;
default:
$raffle_name = '舰队';
break;
}
// switch ($guard['privilege_type']) {
// case 1:
// $raffle_name = '总督';
// break;
// case 2:
// $raffle_name = '提督';
// break;
// case 3:
// $raffle_name = '舰长';
// break;
// default:
// $raffle_name = '舰队';
// break;
// }
// 推入列表
$data = [
'room_id' => $room_id,
'raffle_id' => $guard['id'],
'raffle_name' => $raffle_name,
'wait' => time() + mt_rand(5, 25)
'raffle_name' => $guard['gift_name'],
'wait' => time() + mt_rand(5, 30)
];
Statistics::addPushList(self::ACTIVE_TITLE);
Statistics::addPushList($data['raffle_name']);
array_push(self::$wait_list, $data);
}
return true;
@ -105,7 +106,8 @@ class GuardRaffle extends BaseRaffle
'payload' => Sign::common($payload),
'source' => [
'room_id' => $raffle['room_id'],
'raffle_id' => $raffle['raffle_id']
'raffle_id' => $raffle['raffle_id'],
'raffle_name' => $raffle['raffle_name']
]
]);
}
@ -127,13 +129,14 @@ class GuardRaffle extends BaseRaffle
$de_raw = json_decode($content, true);
// {"code":-403,"data":null,"message":"访问被拒绝","msg":"访问被拒绝"}
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": " . $de_raw['data']['award_name'] . "x" . $de_raw['data']['award_num']);
Statistics::addSuccessList(self::ACTIVE_TITLE);
Statistics::addSuccessList($data['raffle_name']);
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: " . $de_raw['data']['award_name'] . "x" . $de_raw['data']['award_num']);
Statistics::addProfitList($data['raffle_name'] . '-' . $de_raw['data']['award_name'], $de_raw['data']['award_num']);
} elseif (isset($de_raw['msg']) && $de_raw['code'] == -403 && $de_raw['msg'] == '访问被拒绝') {
Log::debug("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['msg']}");
Log::debug("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: {$de_raw['msg']}");
self::pauseLock();
} else {
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['msg']}");
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: " . isset($de_raw['msg']) ? $de_raw['msg'] : $de_raw);
}
}
}

View File

@ -40,7 +40,7 @@ class Judge
}
/**
* @use 判案 TODO: 处理案例已满(MAX20例) / 尝试已实名续期风纪
* @use 判案 TODO: 处理案例已满(MAX20例)
* @param $case_id
* @return bool
*/

View File

@ -225,6 +225,7 @@ class Login
*/
private static function ocrCaptcha($captcha_img)
{
// $url = 'http://captcha-v1.mudew.com:19951/';
$url = 'http://47.102.120.84:19951/';
$payload = [
'image' => (string)$captcha_img

View File

@ -101,7 +101,7 @@ class MasterSite
}
/**
* @use 视频投币 TODO : 处理视频投币硬币少于需要投币数
* @use 视频投币
* @return bool
*/
protected static function coinAdd(): bool
@ -110,29 +110,34 @@ class MasterSite
case 'false':
break;
case 'true':
$av_num = getenv('ADD_COIN_AV_NUM');
$av_num = (int)$av_num;
if ($av_num == 0) {
Log::warning('当前视频投币设置不正确,请检查配置文件!');
die();
// 预计数量 失败默认0 避免损失
$estimate_num = intval(getenv('ADD_COIN_NUM') ?? 0);
// 库存数量
$stock_num = self::getCoin();
// 实际数量 处理硬币库存少于预计数量
$actual_num = intval($estimate_num > $stock_num ? $stock_num : $estimate_num) - self::coinLog();
Log::info("当前硬币库存 {$stock_num} 预计投币 {$estimate_num} 实际投币 {$actual_num}");
// 上限
if ($actual_num <= 0) {
Log::info('今日投币上限已满!');
break;
}
if ($av_num == 1) {
$aid = !empty(getenv('ADD_COIN_AV')) ? getenv('ADD_COIN_AV') : self::getRandomAid();
// 稿件列表
if (gettype('RANDOM_ADD_COIN') =='random'){
// 随机热门稿件榜单
$aids = self::getDayRankingAids($actual_num);
}else{
// 固定获取关注UP稿件榜单, 不足会随机补全
$aids = self::getFollowUpAids($actual_num);
}
Log::info("获取稿件列表: ". implode(" ",$aids));
// 投币
foreach ($aids as $aid) {
self::reward($aid);
} else {
$need_coins = $av_num - self::coinLog();
if ($need_coins <= 0) {
Log::info('今日投币上限已满!');
break;
}
$aids = self::getDayRankingAids($need_coins);
foreach ($aids as $aid) {
self::reward($aid);
}
}
break;
default:
Log::warning('当前视频投币设置不正确,请检查配置文件!');
Log::warning('当前视频投币设置不正确, 请检查配置文件!');
die();
break;
}
@ -163,11 +168,46 @@ class MasterSite
/**
* @use 获取日榜AID
* @param $num
* @use 获取关注UP稿件列表
* @param int $num
* @return array
*/
private static function getDayRankingAids($num): array
private static function getFollowUpAids(int $num): array
{
$aids = [];
$rand_nums = [];
$url = 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new';
$user_info = User::parseCookies();
$payload = [
'uid' => $user_info['uid'],
'type_list' => '8,512,4097,4098,4099,4100,4101'
];
$headers = [
'origin' => 'https://t.bilibili.com',
'referer' => 'https://t.bilibili.com/pages/nav/index_new'
];
$raw = Curl::get('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
foreach ($de_raw['data']['cards'] as $index => $card) {
if ($index >= $num) {
break;
}
array_push($aids, $card['desc']['rid']);
}
// 此处补全缺失
if (count($aids) < $num) {
$aids = array_merge($aids, self::getDayRankingAids($num - count($aids)));
}
return $aids;
}
/**
* @use 获取榜单稿件列表
* @param int $num
* @return array
*/
private static function getDayRankingAids(int $num): array
{
// day: 日榜1 三榜3 周榜7 月榜30
$aids = [];
@ -330,4 +370,24 @@ class MasterSite
}
}
/**
* @use 获取硬币数量
* @return int
*/
private static function getCoin(): int
{
$url = 'https://account.bilibili.com/site/getCoin';
$payload = [];
$headers = [
'referer' => 'https://account.bilibili.com/account/coin',
];
$raw = Curl::get('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
// {"code":0,"status":true,"data":{"money":1707.9}}
if ($de_raw['code'] == 0 && isset($de_raw['data']['money'])) {
return floor($de_raw['data']['money']);
}
return 0;
}
}

View File

@ -28,20 +28,20 @@ class Match
// 'lottery_id' => 46,
// 'status' => true
// ],
'OW' => [
'type_id' => 26,
'room_id' => 14073662,
'short_room_id' => 76,
'lottery_id' => 52,
'status' => true
],
'KPL' => [
'type_id' => 27,
'room_id' => 21144080,
'short_room_id' => 55,
'lottery_id' => 55,
'status' => true
],
// 'OW' => [
// 'type_id' => 26,
// 'room_id' => 14073662,
// 'short_room_id' => 76,
// 'lottery_id' => 52,
// 'status' => true
// ],
// 'KPL' => [
// 'type_id' => 27,
// 'room_id' => 21144080,
// 'short_room_id' => 55,
// 'lottery_id' => 55,
// 'status' => true
// ],
];
public static function run()

View File

@ -67,21 +67,24 @@ class MaterialObject
*/
private static function boxStatus(int $aid, $reply = 'bool')
{
$url = 'https://api.live.bilibili.com/lottery/v1/box/getStatus';
// $url = 'https://api.live.bilibili.com/lottery/v1/box/getStatus';
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v2/Box/getStatus';
$payload = [
'aid' => $aid,
];
$raw = Curl::get('pc', $url, $payload);
$de_raw = json_decode($raw, true);
// {"code":0,"data":null,"message":"ok","msg":"ok"}
// {"code":0,"data":{"title":"荣耀宝箱抽奖","rule":"a 抽奖时间按如下规则抽取一次,重复无效。\nb 获奖者需要再获奖名单公布后一周内反馈姓名、邮寄地址、联系方式,因获奖者逾期查看获奖名单、逾期提交个人资料或个人资料有误,将视为自动放弃获奖资格及由此产生的权利。","current_round":2,"typeB":[{"startTime":"2020-05-18 18:30:00","imgUrl":"https://i0.hdslb.com/bfs/live/f600b89f2c2550b600612feba90e39901a9f027c.jpg","join_start_time":1589796000,"join_end_time":1589797800,"status":4,"list":[{"jp_name":"荣耀路由3","jp_num":"1","jp_id":3181,"jp_type":2,"ex_text":"","jp_pic":"https://i0.hdslb.com/bfs/live/f600b89f2c2550b600612feba90e39901a9f027c.jpg"}],"round_num":1},{"startTime":"2020-05-18 19:00:00","imgUrl":"https://i0.hdslb.com/bfs/live/f600b89f2c2550b600612feba90e39901a9f027c.jpg","join_start_time":1589797800,"join_end_time":1589799600,"status":0,"list":[{"jp_name":"荣耀路由3","jp_num":"1","jp_id":3182,"jp_type":2,"ex_text":"","jp_pic":"https://i0.hdslb.com/bfs/live/f600b89f2c2550b600612feba90e39901a9f027c.jpg"}],"round_num":2},{"startTime":"2020-05-18 19:30:00","imgUrl":"https://i0.hdslb.com/bfs/live/9fcde6f26a546b9dfb5ffc7a0c4f4503a05e16f2.jpg","join_start_time":1589799600,"join_end_time":1589801400,"status":-1,"list":[{"jp_name":"荣耀平板V6","jp_num":"1","jp_id":3183,"jp_type":2,"ex_text":"","jp_pic":"https://i0.hdslb.com/bfs/live/9fcde6f26a546b9dfb5ffc7a0c4f4503a05e16f2.jpg"}],"round_num":3},{"startTime":"2020-05-18 20:00:00","imgUrl":"https://i0.hdslb.com/bfs/live/9fcde6f26a546b9dfb5ffc7a0c4f4503a05e16f2.jpg","join_start_time":1589801400,"join_end_time":1589803200,"status":-1,"list":[{"jp_name":"荣耀平板V6","jp_num":"1","jp_id":3184,"jp_type":2,"ex_text":"","jp_pic":"https://i0.hdslb.com/bfs/live/9fcde6f26a546b9dfb5ffc7a0c4f4503a05e16f2.jpg"}],"round_num":4},{"startTime":"2020-05-18 20:30:00","imgUrl":"https://i0.hdslb.com/bfs/live/9fcde6f26a546b9dfb5ffc7a0c4f4503a05e16f2.jpg","join_start_time":1589803200,"join_end_time":1589805000,"status":-1,"list":[{"jp_name":"荣耀平板V6","jp_num":"1","jp_id":3185,"jp_type":2,"ex_text":"","jp_pic":"https://i0.hdslb.com/bfs/live/9fcde6f26a546b9dfb5ffc7a0c4f4503a05e16f2.jpg"}],"round_num":5},{"startTime":"2020-05-18 21:00:00","imgUrl":"https://i0.hdslb.com/bfs/live/73db69bd5a9e5dedb7d2f32d72fd6248b860e238.jpg","join_start_time":1589805000,"join_end_time":1589806800,"status":-1,"list":[{"jp_name":"荣耀MagicBook Pro","jp_num":"1","jp_id":3186,"jp_type":2,"ex_text":"","jp_pic":"https://i0.hdslb.com/bfs/live/73db69bd5a9e5dedb7d2f32d72fd6248b860e238.jpg"}],"round_num":6},{"startTime":"2020-05-18 22:00:00","imgUrl":"https://i0.hdslb.com/bfs/live/4dba1e8b58c174d5e2311de339b1e02a3ac77a98.jpg","join_start_time":1589806800,"join_end_time":1589810400,"status":-1,"list":[{"jp_name":"荣耀智慧屏新品荣耀MagicBook Pro荣耀平板V6荣耀路由3","jp_num":"1","jp_id":3187,"jp_type":2,"ex_text":"","jp_pic":"https://i0.hdslb.com/bfs/live/4dba1e8b58c174d5e2311de339b1e02a3ac77a98.jpg"}],"round_num":7}],"activity_pic":"https://i0.hdslb.com/bfs/live/c3ed87683f6e87d256d1f5fdddbfb220fc4c2cdf.png","activity_id":556,"weight":20,"background":"https://i0.hdslb.com/bfs/live/84cd59bcb1e977359df618dbeb0f7828751f457c.png","title_color":"#FFFFFF","closeable":0,"jump_url":"https://live.bilibili.com/p/html/live-app-treasurebox/index.html?is_live_half_webview=1\u0026hybrid_biz=live-app-treasurebox\u0026hybrid_rotate_d=1\u0026hybrid_half_ui=1,3,100p,70p,0,0,30,100;2,2,375,100p,0,0,30,100;3,3,100p,70p,0,0,30,100;4,2,375,100p,0,0,30,100;5,3,100p,70p,0,0,30,100;6,3,100p,70p,0,0,30,100;7,3,100p,70p,0,0,30,100\u0026aid=556"},"message":"","msg":""}
switch ($reply) {
// 等于0是有抽奖返回false
case 'bool':
if ($de_raw['code'] == 0) {
if (!is_null($de_raw['data'])) {
return false;
}
return true;
case 'array':
if ($de_raw['code'] == 0) {
if (!is_null($de_raw['data'])) {
return $de_raw;
}
return [];
@ -175,7 +178,8 @@ class MaterialObject
$aid = $lottery['aid'];
$num = $lottery['num'];
Log::notice("实物抽奖 {$aid} 轮次 {$num} 可参与抽奖~");
$url = 'https://api.live.bilibili.com/lottery/v1/Box/draw';
// $url = 'https://api.live.bilibili.com/lottery/v1/Box/draw';
$url = 'https://api.live.bilibili.com/xlive/lottery-interface/v2/Box/draw';
$payload = [
'aid' => $aid,
'number' => $num,

View File

@ -122,6 +122,12 @@ class Notice
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 程序运行错误: ' . self::$result,
];
break;
case 'key_expired':
$info = [
'title' => '监控KEY异常',
'content' => '[' . $now_time . ']' . ' 用户: ' . self::$uname . ' 监控KEY到期或者错误请及时查错或续期后重试哦~',
];
break;
default:
$info = [
'title' => '推送消息异常记录',

View File

@ -57,10 +57,10 @@ class PkRaffle extends BaseRaffle
$data = [
'room_id' => $room_id,
'raffle_id' => $pk['id'],
'raffle_name' => '大乱斗',
'raffle_name' => $pk['title'],
'wait' => time() + mt_rand(5, 25)
];
Statistics::addPushList(self::ACTIVE_TITLE);
Statistics::addPushList($data['raffle_name']);
array_push(self::$wait_list, $data);
}
return true;
@ -89,7 +89,8 @@ class PkRaffle extends BaseRaffle
'payload' => Sign::common($payload),
'source' => [
'room_id' => $raffle['room_id'],
'raffle_id' => $raffle['raffle_id']
'raffle_id' => $raffle['raffle_id'],
'raffle_name' => $raffle['raffle_name']
]
]);
}
@ -116,13 +117,16 @@ class PkRaffle extends BaseRaffle
* {"code":-403,"data":null,"message":"访问被拒绝","msg":"访问被拒绝"}
*/
if (isset($de_raw['code']) && $de_raw['code'] == 0) {
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['data']['award_text']}");
Statistics::addSuccessList(self::ACTIVE_TITLE);
Statistics::addSuccessList($data['raffle_name']);
$award_text = $de_raw['data']['award_text'];
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: {$award_text}");
// 收益
Statistics::addProfitList($data['raffle_name'] . '-' . explode('X', $award_text)[0], $de_raw['data']['award_num']);
} elseif (isset($de_raw['msg']) && $de_raw['code'] == -403 && $de_raw['msg'] == '访问被拒绝') {
Log::debug("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['message']}");
Log::debug("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: {$de_raw['message']}");
self::pauseLock();
} else {
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} " . self::ACTIVE_TITLE . ": {$de_raw['message']}");
Log::notice("房间 {$data['room_id']} 编号 {$data['raffle_id']} {$data['raffle_name']}: {$de_raw['message']}");
}
}
}

View File

@ -37,7 +37,7 @@ class Silver2Coin
*/
protected static function appSilver2coin(): bool
{
sleep(1);
sleep(0.5);
$url = 'https://api.live.bilibili.com/AppExchange/silver2coin';
$payload = [];
$raw = Curl::get('app', $url, Sign::common($payload));
@ -61,7 +61,7 @@ class Silver2Coin
*/
protected static function pcSilver2coin(): bool
{
sleep(1);
sleep(0.5);
$payload = [];
$url = "https://api.live.bilibili.com/exchange/silver2coin";
$url = "https://api.live.bilibili.com/pay/v1/Exchange/silver2coin";
@ -72,7 +72,6 @@ class Silver2Coin
return false;
}
Log::info('[PC]银瓜子兑换硬币: ' . $de_raw['msg']);
// TODO
return true;
}
}

View File

@ -11,8 +11,8 @@
namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
use MathieuViossat\Util\ArrayToTextTable;
class Statistics
@ -22,6 +22,7 @@ class Statistics
private static $push_list = [];
private static $join_list = [];
private static $success_list = [];
private static $profit_list = [];
public static function run()
@ -38,12 +39,13 @@ class Statistics
/**
* @use 添加推送
* @param string $key
* @param int $num
* @return bool
*/
public static function addPushList(string $key): bool
public static function addPushList(string $key, int $num = 1): bool
{
self::initKeyValue(self::$push_list, $key);
self::$push_list[$key]++;
self::valIncrease(self::$push_list, $key);
return true;
}
@ -51,12 +53,13 @@ class Statistics
/**
* @use 添加参与
* @param string $key
* @param int $num
* @return bool
*/
public static function addJoinList(string $key): bool
public static function addJoinList(string $key, int $num = 1): bool
{
self::initKeyValue(self::$join_list, $key);
self::$join_list[$key]++;
self::valIncrease(self::$join_list, $key);
return true;
}
@ -64,50 +67,220 @@ class Statistics
/**
* @use 添加成功
* @param string $key
* @param int $num
* @return bool
*/
public static function addSuccessList(string $key): bool
public static function addSuccessList(string $key, int $num = 1): bool
{
self::initKeyValue(self::$success_list, $key);
self::$success_list[$key]++;
self::valIncrease(self::$success_list, $key);
return true;
}
/**
* @use 添加收益
* @param string $title
* @param int $num
* @param int $updated_time
* @return bool
*/
public static function addProfitList(string $title, int $num, int $updated_time = 0): bool
{
self::initKeyValue(self::$profit_list, $title, 0, 'num');
self::initKeyValue(self::$profit_list, $title, time(), 'updated_time');
self::valIncrease(self::$profit_list, $title, $num, 'num');
self::valReplace(self::$profit_list, $title, time(), 'updated_time');
return true;
}
/**
* @use 转换时间
* @param int $the_time
* @return string
*/
private static function timeTran(int $the_time): string
{
$t = time() - $the_time;//现在时间-发布时间 获取时间差
$f = [
'31536000' => '年',
'2592000' => '个月',
'604800' => '星期',
'86400' => '天',
'3600' => '小时',
'60' => '分钟',
'1' => '秒',
'0' => '秒'
];
foreach ($f as $k => $v) {
if (0 != $c = floor($t / (int)$k)) {
return $c . $v . '前';
}
}
}
/**
* @use 初始化键值
* @param array $target
* @param string $key
* @param int $value
* @param null $second_key
* @return bool
*/
private static function initKeyValue(array &$target, string $key, $value = 0): bool
private static function initKeyValue(array &$target, string $key, $value = 0, $second_key = null): bool
{
if (!array_key_exists($key, $target)) {
$target[$key] = $value;
if (!array_key_exists(self::getTodayKey(), $target)) {
$target[self::getTodayKey()] = [];
}
if (!array_key_exists($key, $target[self::getTodayKey()])) {
$target[self::getTodayKey()][$key] = is_null($second_key) ? $value : [];
}
if (!is_null($second_key) && !array_key_exists($second_key, $target[self::getTodayKey()][$key])) {
$target[self::getTodayKey()][$key][$second_key] = $value;
}
return true;
}
/**
* @use 输出结果
* @use 获取结果
* @param array $target
* @param string $key
* @param null $second_key
* @return mixed
*/
private static function getResult(array &$target, string $key, $second_key = null)
{
is_null($second_key) ? self::initKeyValue($target, $key) : self::initKeyValue($target, $key, 0, $second_key);
return is_null($second_key) ? $target[self::getTodayKey()][$key] : $target[self::getTodayKey()][$key][$second_key];
}
/**
* @use 获取所有结果
* @param array $target
* @param string $key
* @param string $second_key
* @return int
*/
private static function getResults(array &$target, string $key, $second_key = null)
{
$results = 0;
is_null($second_key) ? self::initKeyValue($target, $key) : self::initKeyValue($target, $key, 0, $second_key);
foreach ($target as $item) {
is_null($second_key) ? $results += intval($item[$key]) : $results += intval($item[$key][$second_key]);
}
return $results;
}
/**
* @use 变量增加
* @param array $target
* @param string $key
* @param int $num
* @param null $second_key
* @return bool
*/
private static function outputResult(): bool
private static function valIncrease(array &$target, string $key, $num = 1, $second_key = null)
{
if (empty(self::$push_list)) {
return false;
}
Log::info("-----------密----------封---------线------------");
foreach (self::$push_list as $key => $val) {
$title = $key;
$push_num = isset(self::$push_list[$key]) ? self::$push_list[$key] : 0;
$join_num = isset(self::$join_list[$key]) ? self::$join_list[$key] : 0;
$success_num = isset(self::$success_list[$key]) ? self::$success_list[$key] : 0;
$content = "{$title}: #推送 {$push_num} #参与 {$join_num} #成功 {$success_num}";
Log::notice($content);
}
Log::info("-----------密----------封---------线------------");
is_null($second_key) ? $target[self::getTodayKey()][$key] += $num : $target[self::getTodayKey()][$key][$second_key] += $num;
return true;
}
/**
* @use 变量替换
* @param array $target
* @param string $key
* @param null $data
* @param string $second_key
* @return bool
*/
private static function valReplace(array &$target, string $key, $data = null, $second_key = '')
{
is_null($second_key) ? $target[self::getTodayKey()][$key] = $data : $target[self::getTodayKey()][$key][$second_key] = $data;
return true;
}
/**
* @use 获取 table -> tr -> td
* @return array
*/
private static function getTrList(): array
{
$tr_list_count = [];
$tr_list_profit = [];
// 统计数量
foreach (self::$push_list as $index => $item) {
foreach ($item as $key => $val) {
$td = [
'名称 (总计/今日)' => $key,
'推送' => self::getResults(self::$push_list, $key) . '/' . self::getResult(self::$push_list, $key),
'参与' => self::getResults(self::$join_list, $key) . '/' . self::getResult(self::$join_list, $key),
'成功' => self::getResults(self::$success_list, $key) . '/' . self::getResult(self::$success_list, $key),
];
array_push($tr_list_count, $td);
}
}
// 收益数量
foreach (self::$profit_list as $index => $item) {
foreach ($item as $key => $val) {
$td = [
'名称 (总计/今日)' => explode('-', $key)[0],
'数量' => self::getResults(self::$profit_list, $key, 'num') . '/' . self::getResult(self::$profit_list, $key, 'num'),
'奖品' => explode('-', $key)[1],
'更新时间' => self::timeTran(self::getResult(self::$profit_list, $key, 'updated_time')),
];
array_push($tr_list_profit, $td);
}
}
return [$tr_list_count, $tr_list_profit];
}
/**
* @use 数据数组转表格数组
* @param array $data
* @return array
*/
private static function arrayToTable(array $data): array
{
$th_list = [];
if ($data) {
$renderer = new ArrayToTextTable($data);
foreach (explode("\n", $renderer->getTable()) as $value) {
if ($value) {
array_push($th_list, $value);
}
}
}
return $th_list;
}
/**
* @use 打印表格
*/
private static function outputResult()
{
$arr_tr_list = self::getTrList();
foreach ($arr_tr_list as $tr_list) {
$th_list = self::arrayToTable($tr_list);
foreach ($th_list as $th) {
Log::notice($th);
}
}
}
/**
* @use 获取今日KEY
* @return string
*/
private static function getTodayKey(): string
{
$ts = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
// 1592668800 -> 5bb4085b4cc25bc0
return md5($ts);
}
}

View File

@ -65,7 +65,7 @@ class StormRaffle extends BaseRaffle
'raffle_name' => '节奏风暴',
'wait' => time()
];
Statistics::addPushList(self::ACTIVE_TITLE);
Statistics::addPushList($data['raffle_name']);
array_push(self::$wait_list, $data);
return true;
}
@ -118,8 +118,10 @@ class StormRaffle extends BaseRaffle
break;
}
if ($de_raw['code'] == 0) {
Statistics::addSuccessList(self::ACTIVE_TITLE);
Log::notice(self::formatInfo($raffle['raffle_id'], $num, $de_raw['data']['mobile_content']));
$data = $de_raw['data'];
Statistics::addSuccessList($raffle['raffle_name']);
Log::notice(self::formatInfo($raffle['raffle_id'], $num, $data['mobile_content']));
Statistics::addProfitList($data['title'] . '-' . $data['gift_name'], $data['gift_num']);
break;
}
if (!isset($de_raw['msg'])) {

View File

@ -94,7 +94,7 @@ class User
'room_id' => $room_id ?? getenv('ROOM_ID')
];
$raw = Curl::get('pc', $url, $payload);
return json_decode($raw, true);;
return json_decode($raw, true);
}
@ -134,10 +134,10 @@ class User
}
/**
* @use 获取关注列表
* @use 获取全部关注列表
* @return array
*/
public static function fetchFollowings(): array
public static function fetchAllFollowings(): array
{
$user_info = User::parseCookies();
$uid = $user_info['uid'];
@ -169,6 +169,46 @@ class User
}
/**
* @use 获取分组关注列表
* @param int $tag_id
* @param int $page_num
* @param int $page_size
* @return array
*/
public static function fetchTagFollowings(int $tag_id = 0, int $page_num = 100, int $page_size = 50): array
{
$user_info = User::parseCookies();
$uid = $user_info['uid'];
$followings = [];
for ($i = 1; $i < $page_num; $i++) {
$url = "https://api.bilibili.com/x/relation/tag";
$payload = [
'mid' => $uid,
'tagid' => $tag_id,
'pn' => $i,
'ps' => $page_size,
];
$headers = [
'referer' => "https://space.bilibili.com/{$uid}/fans/follow?tagid={$tag_id}",
];
$raw = Curl::get('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
if ($de_raw['code'] == 0 && isset($de_raw['data'])) {
foreach ($de_raw['data'] as $user) {
array_push($followings, $user['mid']);
}
if (count($de_raw['data']) != $page_size || empty($de_raw['data'])) {
break;
}
continue;
}
break;
}
return $followings;
}
/**
* @use 设置用户关注
* @param int $follow_uid
@ -204,9 +244,9 @@ class User
/**
* @use 创建关注分组
* @param string $tag_name
* @return bool
* @return int
*/
public static function createRelationTag(string $tag_name): bool
public static function createRelationTag(string $tag_name): int
{
$user_info = User::parseCookies();
$url = 'https://api.bilibili.com/x/relation/tag/create?cross_domain=true';
@ -222,10 +262,10 @@ class User
$raw = Curl::post('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
// {"code":0,"message":"0","ttl":1,"data":{"tagid":244413}}
if ($de_raw['code'] == 0) {
return true;
if ($de_raw['code'] == 0 && isset($de_raw['data']['tagid'])) {
return $de_raw['data']['tagid'];
}
return false;
return 0;
}
/**
@ -257,4 +297,27 @@ class User
return false;
}
/**
* @use 获取分组列表
* @return array
*/
public static function fetchTags(): array
{
$user_info = User::parseCookies();
$tags = [];
$url = 'https://api.bilibili.com/x/relation/tags';
$payload = [];
$headers = [
'referer' => "https://space.bilibili.com/{$user_info['uid']}/fans/follow",
];
$raw = Curl::get('pc', $url, $payload, $headers);
$de_raw = json_decode($raw, true);
if ($de_raw['code'] == 0 && isset($de_raw['data'])) {
foreach ($de_raw['data'] as $tag) {
$tags[$tag['tagid']] = $tag['name'];
}
}
return $tags;
}
}

View File

@ -9,7 +9,6 @@
* Source: https://github.com/anhao/bv2av/
*/
namespace BiliHelper\Tool;
use BiliHelper\Core\Log;

View File

@ -1,5 +1,13 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2020 ~ 2021
* Source: https://github.com/anhao/bv2av/
*/
namespace BiliHelper\Tool;

View File

@ -50,12 +50,34 @@ trait TimeLock
/**
* @use 定时
* @param int $hour
* @param int $minute
* @param int $seconds
* @return int
*/
public static function timing(int $hour): int
public static function timing(int $hour, int $minute = 0, int $seconds = 0): int
{
// now today tomorrow yesterday
return strtotime('tomorrow') + ($hour * 60 * 60) - time();
return strtotime('tomorrow') + ($hour * 60 * 60) + ($minute * 60) + ($seconds) - time();
}
/**
* @use 判断是否在时间内
* @param string $first_time
* @param string $second_time
* @return bool
*/
public static function inTime(string $first_time, string $second_time): bool
{
#判断当前时间是否在时间段内,如果是,则执行
$Day = date('Y-m-d ', time());
$timeBegin = strtotime($Day . $first_time);
$timeEnd = strtotime($Day . $second_time);
$curr_time = time();
if ($curr_time >= $timeBegin && $curr_time <= $timeEnd) {
return true;
}
return false;
}
/**