diff --git a/.gitignore b/.gitignore index c598a49..e72cf9c 100644 --- a/.gitignore +++ b/.gitignore @@ -28,10 +28,12 @@ conf/user1.ini /conf/test1.ini /log/ /src/backup/ +script.php # ignore all files in lib/ task/* # except for .gitkeep !.gitkeep # ignore TODO file in root directory,not subdir/TODO -/TODO \ No newline at end of file +/TODO +/Todo \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 15080ab..aff8c0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,33 @@ # 本项目Log +[comment]: <> (
) +[comment]: <> ( 更新历史latest) + +[comment]: <> (
) + +## v0.9.7.210714 alpha (2021-07-14) + +### Added + +- 添加脚本模式 `php index.php -?` +- + +### Changed + +- 省略 +- + +### Fixed + +- 省略 +- + +### Remarks + +- 注意配置文件有些许改动 +- ## v0.9.6.210625 alpha (2021-06-25) diff --git a/README.md b/README.md index 022ba53..078c81e 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,14 @@ ![](https://img.shields.io/github/stars/lkeme/BiliHelper-personal.svg?style=plastic&logo=appveyor "Star数量") ![](https://img.shields.io/github/forks/lkeme/BiliHelper-personal.svg?style=plastic&logo=stackshare "Fork数量") ![](https://img.shields.io/github/contributors/lkeme/BiliHelper-personal "贡献者") +![](https://img.shields.io/github/repo-size/lkeme/BiliHelper-personal?style=flat-square&label=files&color=cf8ef4&labelColor=373e4dl "文件大小") [![Docker Pulls](https://img.shields.io/docker/pulls/lkeme/bilihelper-personal?style=flat-square)](https://hub.docker.com/r/lkeme/bilihelper-personal)

- + @@ -30,48 +31,53 @@ ---- 免费的东西总是得不到人的珍惜。 ---- 只有花大价钱去买到的东西,才会令人信任。 ``` +## 🖥️星图 + +[![Stargazers over time](https://starchart.cc/lkeme/BiliHelper-personal.svg)](https://starchart.cc/lkeme/BiliHelper-personal) +[![Stargazers over time](https://starchart.cc/lkeme/BiliHelper.svg)](https://starchart.cc/lkeme/BiliHelper) ## 功能组件 以下任务都是按设定周期自动执行,`true`为正常使用,`false`为暂停使用或抛弃。 -| plugin | status | version | description | -|-----------------|--------|----------|---------------------------------------------| -| CheckUpdate | true | 21.06.25 | 程序检查更新 | -| Login | true | 21.06.25 | 账号登录、刷新、维持 | -| Schedule | true | 21.06.25 | 控制插件运行周期 | -| MainSite | true | 21.06.25 | 投币、观看、分享视频 (速升6级不是梦) | -| DailyBag | true | 21.06.25 | 双端领取日常/周常礼包 | -| ManGa | true | 21.06.25 | 漫画签到、分享 | -| ActivityLottery | true | 21.06.25 | 主站活动九宫格抽奖 | -| Competition | true | 21.06.25 | 游戏赛事竞猜 | -| DoubleHeart | true | 21.06.25 | 双端心跳 (姥爷直播经验) | -| DailyTask | true | 21.06.25 | 直播每日任务(签到、观看) | -| Barrage | true | 21.06.25 | 保持活跃弹幕 | -| Silver2Coin | true | 21.06.25 | 银瓜子兑换硬币 | -| Judge | true | 21.06.25 | 风纪委员投票 | -| GiftSend | true | 21.06.25 | 礼物赠送、维持每日勋章亲密度 | -| GroupSignIn | true | 21.06.25 | 友爱社签到 | -| GiftHeart | true | 21.06.25 | 日常心跳每日礼包礼物 | -| SmallHeart | true | 21.06.25 | 直播挂机,每日24个小心心 | -| MaterialObject | true | 21.06.25 | 直播金色宝箱实物抽奖 | -| AloneTcpClient | true | 21.06.25 | 作者的独立直播监控(可支持本项目哦) | -| ZoneTcpClient | true | 21.06.25 | 官方的分区直播监控 | -| StormRaffle | true | 21.06.25 | 直播节奏风暴抽奖、亿元 | -| GiftRaffle | true | 21.06.25 | 直播礼物抽奖 | -| PkRaffle | true | 21.06.25 | 直播大乱斗抽奖 | -| GuardRaffle | true | 21.06.25 | 直播大航海抽奖 | -| AnchorRaffle | true | 21.06.25 | 直播天选时刻抽奖 | -| GiftRaffle | true | 21.06.25 | 直播礼物抽奖 | -| AwardRecord | true | 21.06.25 | 最新的中奖纪录通知 | -| Forward | true | 21.06.25 | 主站动态抽奖转发 | -| CapsuleLottery | true | 21.06.25 | 直播扭蛋活动抽奖 | -| PolishTheMedal | true | 21.06.25 | 每日自动点亮灰色勋章 | -| CapsuleLottery | true | 21.06.25 | 直播扭蛋活动抽奖 | -| VipPrivilege | true | 21.06.25 | 每月领取年度大会员特权(B币券、会员购优惠券) | -| BpConsumption | true | 21.06.25 | 每月消费使用年度大会员特权的B币券 | -| Statistics | true | 21.06.25 | 全局抽奖结果统计 | -| Silver | false | 21.03.27 | 直播银瓜子自动开启宝箱 | +| plugin | status | version | cycle | description | +|-----------------|--------|----------|--------|---------------------------------------------| +| CheckUpdate | true | 21.07.14 | 待整理 | 程序检查更新 | +| Login | true | 21.07.14 | 待整理 | 账号登录、刷新、维持 | +| Schedule | true | 21.07.14 | 待整理 | 控制插件运行周期 | +| MainSite | true | 21.07.14 | 待整理 | 投币、观看、分享视频 (速升6级不是梦) | +| DailyBag | true | 21.07.14 | 待整理 | 双端领取日常/周常礼包 | +| ManGa | true | 21.07.14 | 待整理 | 漫画签到、分享 | +| ActivityLottery | true | 21.07.14 | 待整理 | 主站活动九宫格抽奖 | +| Competition | true | 21.07.14 | 待整理 | 游戏赛事竞猜 | +| DoubleHeart | true | 21.07.14 | 待整理 | 双端心跳 (姥爷直播经验) | +| DailyTask | true | 21.07.14 | 待整理 | 直播每日任务(签到、观看) | +| Barrage | true | 21.07.14 | 待整理 | 保持活跃弹幕 | +| Silver2Coin | true | 21.07.14 | 待整理 | 银瓜子兑换硬币 | +| Judge | true | 21.07.14 | 待整理 | 风纪委员投票 | +| GiftSend | true | 21.07.14 | 待整理 | 礼物赠送、维持每日勋章亲密度 | +| GroupSignIn | true | 21.07.14 | 待整理 | 友爱社签到 | +| GiftHeart | true | 21.07.14 | 待整理 | 日常心跳每日礼包礼物 | +| SmallHeart | true | 21.07.14 | 待整理 | 直播挂机,每日24个小心心 | +| MaterialObject | true | 21.07.14 | 待整理 | 直播金色宝箱实物抽奖 | +| AloneTcpClient | true | 21.07.14 | 待整理 | 作者的独立直播监控(可支持本项目哦) | +| ZoneTcpClient | true | 21.07.14 | 待整理 | 官方的分区直播监控 | +| StormRaffle | true | 21.07.14 | 待整理 | 直播节奏风暴抽奖、亿元 | +| GiftRaffle | true | 21.07.14 | 待整理 | 直播礼物抽奖 | +| PkRaffle | true | 21.07.14 | 待整理 | 直播大乱斗抽奖 | +| GuardRaffle | true | 21.07.14 | 待整理 | 直播大航海抽奖 | +| AnchorRaffle | true | 21.07.14 | 待整理 | 直播天选时刻抽奖 | +| GiftRaffle | true | 21.07.14 | 待整理 | 直播礼物抽奖 | +| AwardRecord | true | 21.07.14 | 待整理 | 最新的中奖纪录通知 | +| Forward | true | 21.07.14 | 待整理 | 主站动态抽奖转发 | +| CapsuleLottery | true | 21.07.14 | 待整理 | 直播扭蛋活动抽奖 | +| PolishTheMedal | true | 21.07.14 | 待整理 | 每日自动点亮灰色勋章 | +| CapsuleLottery | true | 21.07.14 | 待整理 | 直播扭蛋活动抽奖 | +| VipPrivilege | true | 21.07.14 | 待整理 | 每月领取年度大会员特权(B币券、会员购优惠券) | +| BpConsumption | true | 21.07.14 | 待整理 | 每月消费使用年度大会员特权的B币券 | +| Statistics | true | 21.07.14 | 待整理 | 全局抽奖结果统计 | +| Silver | false | 21.03.27 | 待整理 | 直播银瓜子自动开启宝箱 | + ## 交流反馈 @@ -81,6 +87,8 @@ Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg) | **请不要来问如 有疑问一定要先看看文档或Issue里是否存在相同的问题,再考虑其他渠道咨询。 +[comment]: <> (:cherry_blossom: :gift: :gift_heart: :confetti_ball:) + * [使用文档 / DOC.md](./DOC.md) * [更新日志 / CHANGELOG.md](./CHANGELOG.md) * [配置文档 / WIKI.md](https://github.com/lkeme/BiliHelper-personal/wiki/%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3) diff --git a/composer.json b/composer.json index 05d380a..cb19581 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,9 @@ "klkvsk/json-decode-stream": "^1.0", "sven/file-config": "^3.1", "hassankhan/config": "^2.2", - "lkeme/inifile": "^3.4" + "lkeme/inifile": "^3.4", + "adhocore/cli": "^0.9.0", + "vanilla/garden-cli": "^3.1" }, "license": "MIT", "authors": [ @@ -35,7 +37,7 @@ "BiliHelper\\Plugin\\": "src/plugin", "BiliHelper\\Util\\": "src/util", "BiliHelper\\Tool\\": "src/tool", - "BiliHelper\\Backup\\": "src/backup" + "BiliHelper\\Script\\": "src/script" }, "files": [ "src/core/Helpers.php" diff --git a/composer.lock b/composer.lock index 62ecc11..4ea622f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,80 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "224c6b1ce9f6f5220d3de9434a44da42", + "content-hash": "0678ecd04eed6db66de4668ffffec283", "packages": [ + { + "name": "adhocore/cli", + "version": "0.9.0", + "source": { + "type": "git", + "url": "https://github.com/adhocore/php-cli.git", + "reference": "319c7dd0092c0346d9ad03366cc13d3491b57e34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/adhocore/php-cli/zipball/319c7dd0092c0346d9ad03366cc13d3491b57e34", + "reference": "319c7dd0092c0346d9ad03366cc13d3491b57e34", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ahc\\Cli\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jitendra Adhikari", + "email": "jiten.adhikary@gmail.com" + } + ], + "description": "Command line interface library for PHP", + "keywords": [ + "PHP7", + "argument-parser", + "argv-parser", + "cli", + "cli-action", + "cli-app", + "cli-color", + "cli-option", + "cli-writer", + "command", + "console", + "console-app", + "php-cli", + "stream-input", + "stream-output" + ], + "support": { + "issues": "https://github.com/adhocore/php-cli/issues", + "source": "https://github.com/adhocore/php-cli/tree/0.9.0" + }, + "funding": [ + { + "url": "https://paypal.me/ji10", + "type": "custom" + } + ], + "time": "2021-01-06T00:25:50+00:00" + }, { "name": "amphp/amp", "version": "v2.5.2", @@ -609,16 +681,16 @@ }, { "name": "klkvsk/json-decode-stream", - "version": "v1.0.2", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/klkvsk/json-decode-stream.git", - "reference": "76cbcd9eb9f1860293b82b4f071e76826bc90c82" + "reference": "831b5310b42b51705a2d6ae5353bba7aaa302358" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/klkvsk/json-decode-stream/zipball/76cbcd9eb9f1860293b82b4f071e76826bc90c82", - "reference": "76cbcd9eb9f1860293b82b4f071e76826bc90c82", + "url": "https://api.github.com/repos/klkvsk/json-decode-stream/zipball/831b5310b42b51705a2d6ae5353bba7aaa302358", + "reference": "831b5310b42b51705a2d6ae5353bba7aaa302358", "shasum": "", "mirrors": [ { @@ -663,9 +735,9 @@ ], "support": { "issues": "https://github.com/klkvsk/json-decode-stream/issues", - "source": "https://github.com/klkvsk/json-decode-stream/tree/v1.0.2" + "source": "https://github.com/klkvsk/json-decode-stream/tree/v1.0.3" }, - "time": "2021-03-23T14:26:50+00:00" + "time": "2021-06-29T23:00:36+00:00" }, { "name": "laminas/laminas-servicemanager", @@ -762,16 +834,16 @@ }, { "name": "laminas/laminas-stdlib", - "version": "3.3.1", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "d81c7ffe602ed0e6ecb18691019111c0f4bf1efe" + "reference": "e89c2268c9cad25099f562f7f015c28c5dd383c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/d81c7ffe602ed0e6ecb18691019111c0f4bf1efe", - "reference": "d81c7ffe602ed0e6ecb18691019111c0f4bf1efe", + "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/e89c2268c9cad25099f562f7f015c28c5dd383c9", + "reference": "e89c2268c9cad25099f562f7f015c28c5dd383c9", "shasum": "", "mirrors": [ { @@ -788,9 +860,11 @@ "zendframework/zend-stdlib": "^3.2.1" }, "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", + "laminas/laminas-coding-standard": "~2.3.0", "phpbench/phpbench": "^0.17.1", - "phpunit/phpunit": "~9.3.7" + "phpunit/phpunit": "~9.3.7", + "psalm/plugin-phpunit": "^0.16.0", + "vimeo/psalm": "^4.7" }, "type": "library", "autoload": { @@ -822,7 +896,7 @@ "type": "community_bridge" } ], - "time": "2020-11-19T20:18:59+00:00" + "time": "2021-06-28T21:37:31+00:00" }, { "name": "laminas/laminas-text", @@ -1715,6 +1789,67 @@ } ], "time": "2021-05-27T09:17:38+00:00" + }, + { + "name": "vanilla/garden-cli", + "version": "v3.1.2", + "source": { + "type": "git", + "url": "https://github.com/vanilla/garden-cli.git", + "reference": "d9844c47f4f2812259ee1b583aa66e7b6b5d85c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vanilla/garden-cli/zipball/d9844c47f4f2812259ee1b583aa66e7b6b5d85c5", + "reference": "d9844c47f4f2812259ee1b583aa66e7b6b5d85c5", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/log": "^1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "phpdocumentor/reflection-docblock": "^4.3", + "phpunit/phpunit": "^8", + "vanilla/garden-container": "^3.0", + "vanilla/standards": "^1.3", + "vimeo/psalm": "^3.16" + }, + "suggest": { + "ext-pdo": "Required for the DbUtils class.", + "phpdocumentor/reflection-docblock": "Required for the CliApplication functionality.", + "vanilla/garden-container": "Required for the CliApplication functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Garden\\Cli\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Todd Burry", + "email": "todd@vanillaforums.com" + } + ], + "description": "A full-featured, yet ridiculously simple commandline parser for your next php cli script. Stop fighting with getopt().", + "support": { + "issues": "https://github.com/vanilla/garden-cli/issues", + "source": "https://github.com/vanilla/garden-cli/tree/v3.1.2" + }, + "time": "2020-10-25T13:36:44+00:00" } ], "packages-dev": [], diff --git a/conf/user.ini.example b/conf/user.ini.example index eb1e4dd..f5efb82 100644 --- a/conf/user.ini.example +++ b/conf/user.ini.example @@ -149,7 +149,7 @@ bp2gold = false enable = false clear_dynamic = false clear_group_follow = false -min_fans_num = 4999 +min_fans_num = 15000 auto_reply_text = filter_words = diff --git a/data/filter_library.json b/data/filter_library.json index 9c943ec..2279335 100644 --- a/data/filter_library.json +++ b/data/filter_library.json @@ -640,7 +640,8 @@ "wav使用权", "曲谱", "抽个寂寞", - "儿子" + "儿子", + "送我" ], "uid_list": [ 28008897, diff --git a/data/latest_version.json b/data/latest_version.json index d964f18..ea47efc 100644 --- a/data/latest_version.json +++ b/data/latest_version.json @@ -5,7 +5,7 @@ "source": "https://github.com/lkeme/BiliHelper-personal", "raw_url": "https://cdn.jsdelivr.net/gh/lkeme/BiliHelper-personal@master/data/latest_version.json", "purge_url": "https://purge.jsdelivr.net/gh/lkeme/BiliHelper-personal@master/data/latest_version.json", - "version": "0.9.6.210625", + "version": "0.9.7.210714", "des": "程序有更新,请及时线上查看更新哦~", - "time": "2021年6月25日11:40:35" + "time": "2021年7月14日11:40:35" } \ No newline at end of file diff --git a/index.php b/index.php index 30eb11b..dd2a4b3 100644 --- a/index.php +++ b/index.php @@ -11,10 +11,7 @@ require 'vendor/autoload.php'; - -$filename = $argv[1] ?? 'user.ini'; - $app = new BiliHelper\Core\App(__DIR__); -$app->load($filename) +$app->load($argv) ->inspect() ->start(); diff --git a/src/core/App.php b/src/core/App.php index ecdce88..a235f9a 100644 --- a/src/core/App.php +++ b/src/core/App.php @@ -11,10 +11,14 @@ namespace BiliHelper\Core; use Amp\Loop; +use Ahc\Cli\IO\Interactor; use function Amp\asyncCall; class App { + private $script_mode = false; + private $loop_mode = true; + /** * App constructor. * @param string $app_path @@ -39,39 +43,58 @@ class App /** * @use 加载配置 - * @param string $load_file + * @param $argv * @return $this */ - public function load(string $load_file = 'user.ini'): App + public function load($argv): App { - Config::load($load_file); + $args = (new Command($argv))->run(); + $filename = $args->getArg(0) ?? 'user.ini'; + $this->script_mode = $args->getOpt('script'); + + Config::load($filename); return $this; } /** * @use 新任务 * @param string $taskName + * @param string $dir */ - public function newTask(string $taskName) + public function newTask(string $taskName, string $dir) { - asyncCall(function () use ($taskName) { + asyncCall(function () use ($taskName, $dir) { while (true) { try { - call_user_func(array('BiliHelper\Plugin\\' . $taskName, 'run'), []); + call_user_func(array("BiliHelper\\$dir\\" . $taskName, 'run'), []); } catch (\Throwable $e) { $error_msg = "MSG: {$e->getMessage()} CODE: {$e->getCode()} FILE: {$e->getFile()} LINE: {$e->getLine()}"; Log::error($error_msg); // Notice::push('error', $error_msg); } - yield call_user_func(array('BiliHelper\Plugin\\' . $taskName, 'Delayed'), []); + yield call_user_func(array("BiliHelper\\$dir\\" . $taskName, 'Delayed'), []); } }); } /** - * @use 核心运行 + * @use Script模式 */ - public function start() + private function script_m() + { + $scripts = [ + 'UnFollow' => '批量取消关注(暂测试)', + 'DelDynamic' => '批量清理动态(未完成)' + ]; + + $choice = \BiliHelper\Script\BaseTask::choice($scripts, 'UnFollow'); + $this->newTask($choice, 'Script'); + } + + /** + * @use Loop模式 + */ + private function loop_m() { $plugins = [ 'CheckUpdate', @@ -110,8 +133,24 @@ class App ]; foreach ($plugins as $plugin) { - $this->newTask($plugin); + $this->newTask($plugin, 'Plugin'); } Loop::run(); } + + + /** + * @use 核心运行 + */ + public function start() + { + // Todo 模式名称需要优化 + if ($this->script_mode) { + Log::info('执行Script模式'); + $this->script_m(); + } else { + Log::info('执行Loop模式'); + $this->loop_m(); + } + } } diff --git a/src/core/Command.php b/src/core/Command.php new file mode 100644 index 0000000..be5a97c --- /dev/null +++ b/src/core/Command.php @@ -0,0 +1,52 @@ +argv = $argv; + } + + /** + * @return \Garden\Cli\Args + */ + public function run(): Args + { + $cli = new Cli(); + + $cli->description('BHP命令行工具.') + ->opt('script:s', '执行的Script模式.', false, 'bool'); + + try { + $args = $cli->parse($this->argv, true); + } catch (\Exception $e) { + die('解析命令行参数错误'); + } + return $args; + } + +} + + + + diff --git a/src/core/Curl.php b/src/core/Curl.php index 2a7e19e..d5edcb0 100644 --- a/src/core/Curl.php +++ b/src/core/Curl.php @@ -243,7 +243,7 @@ class Curl 'Connection' => 'keep-alive', // 'Content-Type' => 'application/x-www-form-urlencoded', // 'User-Agent' => 'Mozilla/5.0 BiliDroid/5.51.1 (bbcallen@gmail.com)', - 'User-Agent' => 'Mozilla/5.0 BiliDroid/6.31.0 (bbcallen@gmail.com) os/android model/MuMu mobi_app/android build/6310200 channel/bili innerVer/6310200 osVer/7.1.2 network/2', + 'User-Agent' => 'Mozilla/5.0 BiliDroid/6.32.0 (bbcallen@gmail.com) os/android model/MuMu mobi_app/android build/6320200 channel/bili innerVer/6320200 osVer/7.1.2 network/2', // 'Referer' => 'https://live.bilibili.com/', ]; $pc_headers = [ diff --git a/src/core/Helpers.php b/src/core/Helpers.php index 886fc2b..74b12e2 100644 --- a/src/core/Helpers.php +++ b/src/core/Helpers.php @@ -103,4 +103,15 @@ function getUid(): int function getCsrf(): string { return getConf('csrf', 'login.auth'); +} + + +/** + * @use HttpClient + * @param string $url + * @return \HttpClient + */ +function newHttp(string $url): HttpClient +{ + return new HttpClient($url); } \ No newline at end of file diff --git a/src/core/HttpClient.php b/src/core/HttpClient.php new file mode 100644 index 0000000..ce6a0a6 --- /dev/null +++ b/src/core/HttpClient.php @@ -0,0 +1,159 @@ +ch = curl_init(); + $this->url = $url; + curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false); //忽略 HTTPS 证书错误 + $this->setUA("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36"); + } + + function __destruct() + { + //防止内存泄露 + curl_close($this->ch); + } + + /** + * @use 设置UA + * @param string $ua + * @return $this + */ + public function setUA(string $ua): HttpClient + { + curl_setopt($this->ch, CURLOPT_USERAGENT, $ua); //设置 UA + return $this; + } + + /** + * @use 添加Header + * @param string $header + * @return $this + */ + public function addHeader(string $header): HttpClient + { + array_push($this->headers, $header); + return $this; + } + + /** + * @use 添加Headers + * @param array $headers + * @return $this + */ + public function addHeaders(array $headers): HttpClient + { + foreach ($headers as $key => $value) { + array_push($this->headers, "{$key}: {$value}"); + } + return $this; + } + + /** + * @use 设置Cookie + * @param string $cookie + * @return $this + */ + public function setCookie(string $cookie): HttpClient + { + curl_setopt($this->ch, CURLOPT_COOKIE, $cookie); + return $this; + } + + /** + * @use 设置 url 参数 + */ + public function buildQuery(array $query): HttpClient + { + $this->query = http_build_query($query); + return $this; + } + + /** + * @use 自动将 json 文本解码 + */ + public function asJSON(): object + { + return json_decode($this->ret); + } + + /** + * @use 获取返回结果 + */ + public function asString(): string + { + return $this->ret; + } + + /** + * @use 构造POST表单 + * @param array $form + * @return $this + */ + public function buildPostForm(array $form): HttpClient + { + $this->form = http_build_query($form); + + return $this; + } + + /** + * @use 发送 Get 请求 + */ + public function get(): HttpClient + { + curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query); + curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中 + curl_setopt($this->ch, CURLOPT_HEADER, $this->headers); + $this->ret = curl_exec($this->ch); + return $this; + } + + /** + * @use 发送 POST 请求 + * @param string|null $data 要 POST 的数据 + * @return \HttpClient + */ + public function post(string $data = null): HttpClient + { + curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query); + curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中 + curl_setopt($this->ch, CURLOPT_POST, true); // 发送 POST 请求 + curl_setopt($this->ch, CURLOPT_HEADER, $this->headers); + curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data); + $this->ret = curl_exec($this->ch); + return $this; + } + + + /** + * @use POST表单 + * @param array $form + * @return $this + */ + public function postForm(array $form): HttpClient + { + return $this->post(http_build_query($form)); + } +} + diff --git a/src/plugin/Barrage.php b/src/plugin/Barrage.php index f4e3e11..fb777ec 100644 --- a/src/plugin/Barrage.php +++ b/src/plugin/Barrage.php @@ -86,7 +86,7 @@ class Barrage $response = Live::sendBarragePC($room_id, $content); // {"code":0,"data":[],"message":"","msg":""} // {"code":0,"message":"你被禁言啦","msg":"你被禁言啦"} - // TODO 长度限制 + // Todo 长度限制 if (isset($response['code']) && $response['code'] == 0 && isset($response['data'])) { Log::notice("在直播间@{$room_id} 发送活跃弹幕成功 CODE -> {$response['code']}"); return true; diff --git a/src/plugin/CapsuleLottery.php b/src/plugin/CapsuleLottery.php index 1e83513..fe65cb4 100644 --- a/src/plugin/CapsuleLottery.php +++ b/src/plugin/CapsuleLottery.php @@ -108,7 +108,7 @@ class CapsuleLottery Log::info("执行 {$task['act']->title} #{$task['operation']} 任务"); // 执行任务 switch ($task['operation']) { - // TODO 观看 分享 签到任务 + // Todo 观看 分享 签到任务 case 'watch': $interval = self::xliveHeartBeatTask($task['act']->room_id, 999, 999); self::$interval = $interval == 0 ? 60 : $interval; diff --git a/src/plugin/CheckUpdate.php b/src/plugin/CheckUpdate.php index 3e684e8..53d40da 100644 --- a/src/plugin/CheckUpdate.php +++ b/src/plugin/CheckUpdate.php @@ -47,7 +47,7 @@ class CheckUpdate Log::info('项目已是最新版本'); } else { Log::notice('项目有更新'); - // TODO 完善提示信息 + // Todo 完善提示信息 $time = self::$latest_conf->get('time'); $version = self::$latest_conf->get('version'); $des = self::$latest_conf->get('des'); diff --git a/src/plugin/DataTreating.php b/src/plugin/DataTreating.php index 1faef3b..20732e1 100644 --- a/src/plugin/DataTreating.php +++ b/src/plugin/DataTreating.php @@ -12,7 +12,7 @@ namespace BiliHelper\Plugin; class DataTreating { - // TODO 独立分发 Push||Pull数据 + // Todo 独立分发 Push||Pull数据 /** * @use 抽奖分发 * @param array $data diff --git a/src/plugin/Dynamic.php b/src/plugin/Dynamic.php index 114dea5..fefa5e5 100644 --- a/src/plugin/Dynamic.php +++ b/src/plugin/Dynamic.php @@ -16,7 +16,7 @@ class Dynamic { use FilterWords; - // TODO 活动订阅 + // Todo 活动订阅 // https://www.bilibili.com/blackboard/activity-WeqT10t1ep.html // https://api.vc.bilibili.com/topic_svr/v1/topic_svr/fetch_dynamics?topic_name=%E4%BA%92%E5%8A%A8%E6%8A%BD%E5%A5%96&sortby=2 private static $tags = ['互动抽奖', '抽奖', '转发抽奖', '动态抽奖', '关注+转发']; @@ -52,7 +52,7 @@ class Dynamic $description = $card['item']['description']; } elseif (array_key_exists("content", $card['item'])) { // 子动态 - // TODO 暂时跳过 需要合适的处理方法 + // Todo 暂时跳过 需要合适的处理方法 // description = $card['item']['content']; continue; } else { diff --git a/src/plugin/GroupSignIn.php b/src/plugin/GroupSignIn.php index 91f9408..65d809a 100644 --- a/src/plugin/GroupSignIn.php +++ b/src/plugin/GroupSignIn.php @@ -71,7 +71,7 @@ class GroupSignIn $de_raw = json_decode($raw, true); if ($de_raw['code'] != '0') { - // TODO 任务失败原因 + // Todo 任务失败原因 // {"code": 710001, "msg": "应援失败>_<", "message": "应援失败>_<", "ttl": "1", "data": {"add_num": 0, "status": 0}} if ($de_raw['code'] == '710001') { Log::warning('在应援团{' . $groupInfo['group_name'] . '}中签到失败, 亲密度已达上限'); diff --git a/src/plugin/Judge.php b/src/plugin/Judge.php index babafda..f6c8a9e 100644 --- a/src/plugin/Judge.php +++ b/src/plugin/Judge.php @@ -43,7 +43,7 @@ class Judge } /** - * @use 判案 TODO: 处理案例已满(MAX20例) + * @use 判案 Todo: 处理案例已满(MAX20例) * @param $case_id * @return bool */ diff --git a/src/plugin/Login.php b/src/plugin/Login.php index 7f52d03..53c9b51 100644 --- a/src/plugin/Login.php +++ b/src/plugin/Login.php @@ -29,7 +29,7 @@ class Login return; } Log::info('启动登录程序'); - if (getConf('access_token', 'login.auth') == '') { + if (getAccessToken() == '') { Log::info('准备载入登录令牌'); self::login(); } @@ -117,7 +117,7 @@ class Login { $url = 'https://passport.bilibili.com/api/v2/oauth2/info'; $payload = [ - 'access_token' => getConf('access_token', 'login.auth'), + 'access_token' => getAccessToken(), ]; $data = Curl::get('app', $url, Sign::common($payload)); // {"ts":1234,"code":0,"data":{"mid":1234,"access_token":"1234","expires_in":7759292}} @@ -137,8 +137,8 @@ class Login { $url = 'https://passport.bilibili.com/api/v2/oauth2/refresh_token'; $payload = [ - 'access_token' => getConf('access_token', 'login.auth'), - 'refresh_token' => getConf('refresh_token', 'login.auth'), + 'access_token' => getAccessToken(), + 'refresh_token' => getRefreshToken(), ]; $raw = Curl::post('app', $url, Sign::common($payload)); $de_raw = json_decode($raw, true); @@ -313,7 +313,7 @@ class Login $payload = [ 'cid' => getConf('country_code', 'login.country') , 'tel' => $phone, - 'statistics' => '{"appId":1,"platform":3,"version":"6.31.0","abtest":""}', + 'statistics' => '{"appId":1,"platform":3,"version":"6.32.0","abtest":""}', ]; $raw = Curl::post('app', $url, Sign::login($payload)); $de_raw = json_decode($raw, true); diff --git a/src/plugin/ManGa.php b/src/plugin/ManGa.php index da9f784..1592f30 100644 --- a/src/plugin/ManGa.php +++ b/src/plugin/ManGa.php @@ -40,7 +40,7 @@ class ManGa sleep(1); $url = 'https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn'; $payload = [ - 'access_key' => getConf('access_token', 'login.auth'), + 'access_key' => getAccessToken(), 'ts' => time() ]; $raw = Curl::post('app', $url, Sign::common($payload)); diff --git a/src/plugin/MaterialObject.php b/src/plugin/MaterialObject.php index 2307fdc..ec6b753 100644 --- a/src/plugin/MaterialObject.php +++ b/src/plugin/MaterialObject.php @@ -194,7 +194,7 @@ class MaterialObject */ private static function calcAid($min, $max): bool { - // TODO 优化计算AID算法 + // Todo 优化计算AID算法 if (self::$end_aid != 0 && self::$start_aid != 0) { return false; } diff --git a/src/plugin/Schedule.php b/src/plugin/Schedule.php index 3f154b4..3a2cbad 100644 --- a/src/plugin/Schedule.php +++ b/src/plugin/Schedule.php @@ -17,7 +17,7 @@ class Schedule { use TimeLock; - // TODO 黑白名单|考虑添加到每个插件内部自动添加|优化RUN逻辑代码 + // Todo 黑白名单|考虑添加到每个插件内部自动添加|优化RUN逻辑代码 private static $unlock_hour = 24; private static $unlock_timers = []; private static $sleep_section = []; diff --git a/src/plugin/Sign.php b/src/plugin/Sign.php index 45be081..5c92e79 100644 --- a/src/plugin/Sign.php +++ b/src/plugin/Sign.php @@ -27,7 +27,7 @@ class Sign // $appsecret = '59b43e04ad6965f34319062b478f83dd'; // // $default = [ -// 'access_key' => getConf('access_token', 'login.auth') +// 'access_key' => getAccessToken() // 'actionKey' => 'appkey', // 'appkey' => $appkey, // 'build' => 101800, @@ -52,10 +52,10 @@ class Sign $appsecret = '60698ba2f68e01ce44738920a0ffe768'; $default = [ - 'access_key' => getConf('access_token', 'login.auth'), + 'access_key' => getAccessToken(), 'actionKey' => 'appkey', 'appkey' => $appkey, - 'build' => 6310200, + 'build' => 6320200, 'channel' => 'bili', 'device' => 'phone', 'mobi_app' => 'android', @@ -81,10 +81,10 @@ class Sign $appsecret = '560c52ccd288fed045859ed18bffd973'; $default = [ - 'access_key' => getConf('access_token', 'login.auth'), + 'access_key' => getAccessToken(), 'actionKey' => 'appkey', 'appkey' => $appkey, - 'build' => 6310200, + 'build' => 6320200, 'device' => 'phone', 'mobi_app' => 'android', 'platform' => 'android', diff --git a/src/plugin/Statistics.php b/src/plugin/Statistics.php index 52a8868..3701bfa 100644 --- a/src/plugin/Statistics.php +++ b/src/plugin/Statistics.php @@ -23,7 +23,7 @@ class Statistics private static $success_list = []; private static $profit_list = []; - // TODO 统计开关 统计时间间隔 统计类型 + // Todo 统计开关 统计时间间隔 统计类型 public static function run() { if (self::getLock() > time()) { diff --git a/src/plugin/ZoneTcpClient.php b/src/plugin/ZoneTcpClient.php index c9b167b..555c998 100644 --- a/src/plugin/ZoneTcpClient.php +++ b/src/plugin/ZoneTcpClient.php @@ -499,7 +499,7 @@ class ZoneTcpClient break; Log::debug("Socket debug: select timeout" . PHP_EOL); } - // TODO unable to read from socket[104]: Connection reset by peer + // Todo unable to read from socket[104]: Connection reset by peer $ret = socket_recv($socket, $buffer, $length, 0); if ($ret < 1) { Log::warning("Socket error: [{$ret}] [{$length}]" . PHP_EOL); diff --git a/src/script/BaseTask.php b/src/script/BaseTask.php new file mode 100644 index 0000000..407c479 --- /dev/null +++ b/src/script/BaseTask.php @@ -0,0 +1,63 @@ +choice('Select', $options, $default, true); + static::interactor()->greenBold("You selected: {$options[$option]}", true); + // return $options[$option]; + return $option; + } + + /** + * @use 确认 + * @param string $msg + * @param string $default + * @return bool + */ + public static function confirm(string $msg, string $default = 'n'): bool + { + $confirm = static::interactor()->confirm($msg, $default); // Default: n (no) + if (!$confirm) die(); +// if ($confirm) { // is a boolean +// static::interactor()->greenBold('是 :)', true); // Output green bold text +// } else { +// static::interactor()->redBold('否 :(', true); // Output red bold text +// die(); +// } + return true; + } + + /** + * @return \Ahc\Cli\IO\Interactor + */ + public static function interactor(): Interactor + { + return static::$interactor ?? static::$interactor = new Interactor; + } +} \ No newline at end of file diff --git a/src/script/DelDynamic.php b/src/script/DelDynamic.php new file mode 100644 index 0000000..b12c5d7 --- /dev/null +++ b/src/script/DelDynamic.php @@ -0,0 +1,22 @@ + $up_uname) { + $payload = [ + 'fid' => $up_uid, + 'act' => 2, + 're_src' => 11, + 'csrf' => getCsrf(), + ]; + $headers = [ + 'origin' => 'https://space.bilibili.com', + 'referer' => 'https://space.bilibili.com/' . getUid() . '/fans/follow?tagid=' . $tag_id, + ]; + $raw = Curl::post('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1} + $data = json_decode($raw, true); + if ($data['code'] == 0) { + Log::notice("UP.{$up_uid} - {$up_uname} 取关成功"); + } else { + Log::error("UP.{$up_uid} - {$up_uname} 取关失败 CODE -> {$data['code']} MSG -> {$data['message']} "); + break; + } + sleep(random_int(5, 10)); + } + } + + + /** + * @use 获取分组关注 + * @param $tag_id + * @param int $max_pn + * @param int $max_ps + * @return array + * @throws \Exception + */ + private static function relationTag($tag_id, int $max_pn = 30, int $max_ps = 20): array + { + $following = []; + $url = 'https://api.bilibili.com/x/relation/tag'; + for ($pn = 1; $pn <= $max_pn; $pn++) { + $payload = [ + 'mid' => getUid(), + 'tagid' => $tag_id, + 'pn' => $pn, + 'ps' => $max_ps, + ]; + $headers = [ + 'referer' => 'https://space.bilibili.com/' . getUid() . '/fans/follow', + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + $data = json_decode($raw, true); + if ($data['code'] == 0 && isset($data['data'])) { + // 循环添加到 following + foreach ($data['data'] as $up) { + $following[$up['mid']] = $up['uname']; + } + // 打印和延迟 + Log::info("已获取分组 {$tag_id} 页码 {$pn}"); + sleep(random_int(4, 8)); + // 如果页面不等于 max_ps 跳出 + if (count($data['data']) != $max_ps) { + break; + } + } else { + Log::error("获取分组关注失败 CODE -> {$data['code']} MSG -> {$data['message']} "); + break; + } + } + $following_num = count($following); + Log::notice("已获取分组 {$tag_id} 有效关注数 {$following_num}"); + return $following; + } + + + /** + * @use 获取分组 + * @return mixed + */ + private static function relationTags() + { + $url = 'https://api.bilibili.com/x/relation/tags'; + $payload = []; + $headers = [ + 'referer' => 'https://space.bilibili.com/', + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + $data = json_decode($raw, true); + if ($data['code'] == 0 && isset($data['data'])) { + $options = []; + foreach ($data['data'] as $tag) { + $options[$tag['tagid']] = "分组:{$tag['name']} - 关注数:{$tag['count']}"; + } + $option = self::choice($options); + Log::notice("已获取分组 {$option} - {$options[$option]}"); + return $option; + } else { + Log::error("获取关注分组失败 CODE -> {$data['code']} MSG -> {$data['message']} "); + die(); + } + } + +} \ No newline at end of file diff --git a/src/script/User.php b/src/script/User.php new file mode 100644 index 0000000..4036c42 --- /dev/null +++ b/src/script/User.php @@ -0,0 +1,57 @@ + {$data['code']} MSG -> {$data['message']} "); + die(); + } + return true; + } + + /** + * @use 用户 + * @return mixed + */ + public static function userInfo() + { + $url = 'https://api.bilibili.com/x/web-interface/nav'; + $payload = []; + $headers = [ + 'origin' => 'https://space.bilibili.com', + 'referer' => 'https://space.bilibili.com/' . getUid(), + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + return json_decode($raw, true); + } + + +} \ No newline at end of file diff --git a/src/tool/UserAgent.php b/src/tool/UserAgent.php new file mode 100644 index 0000000..30f011f --- /dev/null +++ b/src/tool/UserAgent.php @@ -0,0 +1,401 @@ + [ + 'GT-I9:number2-5:00 Build/JDQ39', + 'Nokia 3:number1-3:[10|15] Build/IMM76D', + '[SAMSUNG |]SM-G3:number1-5:0[R5|I|V|A|T|S] Build/JLS36C', + 'Ascend G3:number0-3:0 Build/JLS36I', + '[SAMSUNG |]SM-G3:number3-6::number1-8::number0-9:[V|A|T|S|I|R5] Build/JLS36C', + 'HUAWEI G6-L:number10-11: Build/HuaweiG6-L:number10-11:', + '[SAMSUNG |]SM-[G|N]:number7-9:1:number0-8:[S|A|V|T] Build/[JLS36C|JSS15J]', + '[SAMSUNG |]SGH-N0:number6-9:5[T|V|A|S] Build/JSS15J', + 'Samsung Galaxy S[4|IV] Mega GT-I:number89-95:00 Build/JDQ39', + 'SAMSUNG SM-T:number24-28:5[s|a|t|v] Build/[JLS36C|JSS15J]', + 'HP :number63-73:5 Notebook PC Build/[JLS36C|JSS15J]', + 'HP Compaq 2:number1-3:10b Build/[JLS36C|JSS15J]', + 'HTC One 801[s|e] Build/[JLS36C|JSS15J]', + 'HTC One max Build/[JLS36C|JSS15J]', + 'HTC Xplorer A:number28-34:0[e|s] Build/GRJ90' + ], + '4.4' => [ + 'XT10:number5-8:0 Build/SU6-7.3', + 'XT10:number12-52: Build/[KXB20.9|KXC21.5]', + 'Nokia :number30-34:10 Build/IMM76D', + 'E:number:20-23::number0-3::number0-4: Build/24.0.[A|B].1.34', + '[SAMSUNG |]SM-E500[F|L] Build/KTU84P', + 'LG Optimus G Build/KRT16M', + 'LG-E98:number7-9: Build/KOT49I', + 'Elephone P:number2-6:000 Build/KTU84P', + 'IQ450:number0-4: Quad Build/KOT49H', + 'LG-F:number2-5:00[K|S|L] Build/KOT49[I|H]', + 'LG-V:number3-7::number0-1:0 Build/KOT49I', + '[SAMSUNG |]SM-J:number1-2::number0-1:0[G|F] Build/KTU84P', + '[SAMSUNG |]SM-N80:number0-1:0 Build/[KVT49L|JZO54K]', + '[SAMSUNG |]SM-N900:number5-8: Build/KOT49H', + '[SAMSUNG-|]SGH-I337[|M] Build/[JSS15J|KOT49H]', + '[SAMSUNG |]SM-G900[W8|9D|FD|H|V|FG|A|T] Build/KOT49H', + '[SAMSUNG |]SM-T5:number30-35: Build/[KOT49H|KTU84P]', + '[Google |]Nexus :number5-7: Build/KOT49H', + 'LG-H2:number0-2:0 Build/KOT49[I|H]', + 'HTC One[_M8|_M9|0P6B|801e|809d|0P8B2|mini 2|S][ dual sim|] Build/[KOT49H|KTU84L]', + '[SAMSUNG |]GT-I9:number3-5:0:number0-6:[V|I|T|N] Build/KOT49H', + 'Lenovo P7:number7-8::number1-6: Build/[Lenovo|JRO03C]', + 'LG-D95:number1-8: Build/KOT49[I|H]', + 'LG-D:number1-8::number0-8:0 Build/KOT49[I|H]', + 'Nexus5 V:number6-7:.1 Build/KOT49H', + 'Nexus[_|] :number4-10: Build/[KOT49H|KTU84P]', + 'Nexus[_S_| S ][4G |]Build/GRJ22', + '[HM NOTE|NOTE-III|NOTE2 1LTE[TD|W|T]', + 'ALCATEL ONE[| ]TOUCH 70:number2-4::number0-9:[X|D|E|A] Build/KOT49H', + 'MOTOROLA [MOTOG|MSM8960|RAZR] Build/KVT49L' + ], + '5.0' => [ + 'Nokia :number10-11:00 [wifi|4G|LTE] Build/GRK39F', + 'HTC 80:number1-2[s|w|e|t] Build/[LRX22G|JSS15J]', + 'Lenovo A7000-a Build/LRX21M;', + 'HTC Butterfly S [901|919][s|d|] Build/LRX22G', + 'HTC [M8|M9|M8 Pro Build/LRX22G', + 'LG-D3:number25-37: Build/LRX22G', + 'LG-D72:number0-9: Build/LRX22G', + '[SAMSUNG |]SM-G4:number0-9:0 Build/LRX22[G|C]', + '[|SAMSUNG ]SM-G9[00|25|20][FD|8|F|F-ORANGE|FG|FQ|H|I|L|M|S|T] Build/[LRX21T|KTU84F|KOT49H]', + '[SAMSUNG |]SM-A:number7-8:00[F|I|T|H|] Build/[LRX22G|LMY47X]', + '[SAMSUNG-|]SM-N91[0|5][A|V|F|G|FY] Build/LRX22C', + '[SAMSUNG |]SM-[T|P][350|550|555|355|805|800|710|810|815] Build/LRX22G', + 'LG-D7:number0-2::number0-9: Build/LRX22G', + '[LG|SM]-[D|G]:number8-9::number0-5::number0-9:[|P|K|T|I|F|T1] Build/[LRX22G|KOT49I|KVT49L|LMY47X]' + ], + '5.1' => [ + 'Nexus :number5-9: Build/[LMY48B|LRX22C]', + '[|SAMSUNG ]SM-G9[28|25|20][X|FD|8|F|F-ORANGE|FG|FQ|H|I|L|M|S|T] Build/[LRX22G|LMY47X]', + '[|SAMSUNG ]SM-G9[35|350][X|FD|8|F|F-ORANGE|FG|FQ|H|I|L|M|S|T] Build/[MMB29M|LMY47X]', + '[MOTOROLA |][MOTO G|MOTO G XT1068|XT1021|MOTO E XT1021|MOTO XT1580|MOTO X FORCE XT1580|MOTO X PLAY XT1562|MOTO XT1562|MOTO XT1575|MOTO X PURE XT1575|MOTO XT1570 MOTO X STYLE] Build/[LXB22|LMY47Z|LPC23|LPK23|LPD23|LPH223]' + ], + '6.0' => [ + '[SAMSUNG |]SM-[G|D][920|925|928|9350][V|F|I|L|M|S|8|I] Build/[MMB29K|MMB29V|MDB08I|MDB08L]', + 'Nexus :number5-7:[P|X|] Build/[MMB29K|MMB29V|MDB08I|MDB08L]', + 'HTC One[_| ][M9|M8|M8 Pro] Build/MRA58K', + 'HTC One[_M8|_M9|0P6B|801e|809d|0P8B2|mini 2|S][ dual sim|] Build/MRA58K' + ], + '7.0' => [ + 'Pixel [XL|C] Build/[NRD90M|NME91E]', + 'Nexus :number5-9:[X|P|] Build/[NPD90G|NME91E]', + '[SAMSUNG |]GT-I:number91-98:00 Build/KTU84P', + 'Xperia [V |]Build/NDE63X', + 'LG-H:number90-93:0 Build/NRD90[C|M]' + ], + '7.1' => [ + 'Pixel [XL|C] Build/[NRD90M|NME91E]', + 'Nexus :number5-9:[X|P|] Build/[NPD90G|NME91E]', + '[SAMSUNG |]GT-I:number91-98:00 Build/KTU84P', + 'Xperia [V |]Build/NDE63X', + 'LG-H:number90-93:0 Build/NRD90[C|M]' + ] + ]; + public $locale = 'en-US'; + /** + * List of "OS" strings used for android + * @var array $android_os + */ + public $android_os = [ + 'Linux; Android :androidVersion:; :androidDevice:', + //Todo: Add a $windowsDevices variable that does the same as androidDevice + //'Windows Phone 10.0; Android :androidVersion:; :windowsDevice:', + 'Linux; U; Android :androidVersion:; :androidDevice:', + 'Android; Android :androidVersion:; :androidDevice:' + ]; + /** + * List of "OS" strings used for iOS + * @var array $mobile_ios + */ + public $mobile_ios = [ + 'iphone' => 'iPhone; CPU iPhone OS :number7-11:_:number0-9:_:number0-9:; like Mac OS X;', + 'ipad' => 'iPad; CPU iPad OS :number7-11:_:number0-9:_:number0-9: like Mac OS X;', + 'ipod' => 'iPod; CPU iPod OS :number7-11:_:number0-9:_:number0-9:; like Mac OS X;' + ]; + + /** + * Get a random operating system + * @param string|null $os + * @return string * + */ + public function getOS(string $os = NULL) + { + $_os = []; + if ($os === NULL || in_array($os, ['chrome', 'firefox', 'explorer'])) { + $_os = $os === 'explorer' ? $this->windows_os : array_merge($this->windows_os, $this->linux_os, $this->mac_os); + } else { + $_os += $this->{$os . '_os'}; + } + // randomly select on operating system + $selected_os = rtrim($_os[random_int(0, count($_os) - 1)], ';'); + + // check for spin syntax + if (strpos($selected_os, '[') !== FALSE) { + $selected_os = self::processSpinSyntax($selected_os); + } + + // check for random number syntax + if (strpos($selected_os, ':number') !== FALSE) { + $selected_os = self::processRandomNumbers($selected_os); + } + + if (random_int(1, 100) > 50) { + $selected_os .= '; ' . $this->locale; + } + return $selected_os; + } + + /** + * Get Mobile OS + * @param string|null $os Can specifiy android, iphone, ipad, ipod, or null/blank for random + * @return string * + */ + public function getMobileOS(string $os = NULL) + { + $os = strtolower($os); + $_os = []; + switch ($os) { + case'android': + $_os += $this->android_os; + break; + case 'iphone': + case 'ipad': + case 'ipod': + $_os[] = $this->mobile_ios[$os]; + break; + default: + $_os = array_merge($this->android_os, array_values($this->mobile_ios)); + } + // select random mobile os + $selected_os = rtrim($_os[random_int(0, count($_os) - 1)], ';'); + if (strpos($selected_os, ':androidVersion:') !== FALSE) { + $selected_os = $this->processAndroidVersion($selected_os); + } + if (strpos($selected_os, ':androidDevice:') !== FALSE) { + $selected_os = $this->addAndroidDevice($selected_os); + } + if (strpos($selected_os, ':number') !== FALSE) { + $selected_os = self::processRandomNumbers($selected_os); + } + return $selected_os; + } + + /** + * static::processRandomNumbers + * @param $selected_os + * @return null|string|string[] * + */ + public static function processRandomNumbers($selected_os) + { + return preg_replace_callback('/:number(\d+)-(\d+):/i', function ($matches) { + return random_int($matches[1], $matches[2]); + }, $selected_os); + } + + /** + * static::processSpinSyntax + * @param $selected_os + * @return null|string|string[] * + */ + public static function processSpinSyntax($selected_os) + { + return preg_replace_callback('/\[([\w\-\s|;]*?)\]/i', function ($matches) { + $shuffle = explode('|', $matches[1]); + return $shuffle[array_rand($shuffle)]; + }, $selected_os); + } + + /** + * processAndroidVersion + * @param $selected_os + * @return null|string|string[] * + */ + public function processAndroidVersion($selected_os) + { + $this->androidVersion = $version = $this->androidVersions[array_rand($this->androidVersions)]; + return preg_replace_callback('/:androidVersion:/i', function ($matches) use ($version) { + return $version; + }, $selected_os); + } + + /** + * addAndroidDevice + * @param $selected_os + * @return null|string|string[] * + */ + public function addAndroidDevice($selected_os) + { + $devices = $this->androidDevices[substr($this->androidVersion, 0, 3)]; + $device = $devices[array_rand($devices)]; + + $device = self::processSpinSyntax($device); + return preg_replace_callback('/:androidDevice:/i', function ($matches) use ($device) { + return $device; + }, $selected_os); + } + + /** + * static::chromeVersion + * @param $version + * @return string * + */ + public static function chromeVersion($version): string + { + return random_int($version['min'], $version['max']) . '.0.' . random_int(1000, 4000) + . '.' . random_int(100, 400); + } + + /** + * static::firefoxVersion + * @param $version + * @return string * + */ + public static function firefoxVersion($version): string + { + return random_int($version['min'], $version['max']) . '.' . random_int(0, 9); + } + + /** + * static::windows + * @param $version + * @return string * + */ + public static function windows($version): string + { + return random_int($version['min'], $version['max']) . '.' . random_int(0, 9); + } + + /** + * generate + * @param null $userAgent + * @return string * + */ + public function generate($userAgent = NULL, $locale = null): string + { + + if (!is_null($locale)) + $this->locale = $locale; + + if ($userAgent === NULL) { + $r = random_int(0, 100); + if ($r >= 44) { + $userAgent = array_rand(['firefox' => 1, 'chrome' => 1, 'explorer' => 1]); + } else { + $userAgent = array_rand(['iphone' => 1, 'android' => 1, 'mobile' => 1]); + } + } elseif ($userAgent == 'windows' || $userAgent == 'mac' || $userAgent == 'linux') { + $agents = ['firefox' => 1, 'chrome' => 1]; + if ($userAgent == 'windows') { + $agents['explorer'] = 1; + } + $userAgent = array_rand($agents); + } + $_SESSION['agent'] = $userAgent; + if ($userAgent == 'chrome') { + return 'Mozilla/5.0 (' . $this->getOS($userAgent) . ') AppleWebKit/' . + (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)) + . '.' . random_int(1, 50) . ' (KHTML, like Gecko) Chrome/' . + self::chromeVersion(['min' => 47, 'max' => 55]) . ' Safari/' + . (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)); + } elseif ($userAgent == 'firefox') { + + return 'Mozilla/5.0 (' . $this->getOS($userAgent) . ') Gecko/' + . (random_int(1, 100) > 30 ? '20100101' : '20130401') . ' Firefox/' + . self::firefoxVersion(['min' => 45, 'max' => 74]); + } elseif ($userAgent == 'explorer') { + + return 'Mozilla / 5.0 (compatible; MSIE ' . ($int = random_int(7, 11)) + . '.0; ' . $this->getOS('windows') . ' Trident / ' + . ($int == 7 || $int == 8 ? '4' : ($int == 9 ? '5' : ($int == 10 ? '6' : '7'))) + . '.0)'; + } elseif ($userAgent == 'mobile' + || $userAgent == 'android' + || $userAgent == 'iphone' + || $userAgent == 'ipad' + || $userAgent == 'ipod') { + + return 'Mozilla/5.0 (' . $this->getMobileOS($userAgent) . ') AppleWebKit/' + . (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)) + . '.' . random_int(1, 50) . ' (KHTML, like Gecko) Chrome/' + . self::chromeVersion(['min' => 47, 'max' => 55]) . ' Mobile Safari/' + . (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)) + . '.' . random_int(0, 9); + } else { + new Exception('Unable to determine user agent to generate'); + } + } +} diff --git a/src/util/BaseRaffle.php b/src/util/BaseRaffle.php index d12eb6e..1c80ddb 100644 --- a/src/util/BaseRaffle.php +++ b/src/util/BaseRaffle.php @@ -97,7 +97,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 + // Todo 请求被拦截 412 Log::error("获取抽奖数据错误,{$de_raw['message']}"); return []; } @@ -133,7 +133,7 @@ abstract class BaseRaffle * @param string $type * @return array */ - protected static function arrKeySort($arr, $key, $type = 'asc'): array + protected static function arrKeySort($arr, $key, string $type = 'asc'): array { switch ($type) { case 'desc': @@ -153,7 +153,7 @@ abstract class BaseRaffle * @param bool $filter * @return bool */ - protected static function toRepeatLid($lid, $filter = true): bool + protected static function toRepeatLid($lid, bool $filter = true): bool { $lid = (int)$lid; if (in_array($lid, static::$all_list)) {