diff --git a/README.en.md b/README.en.md
new file mode 100644
index 0000000..eb34c9c
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,77 @@
+
🖼️ Pixiv Daily Ranking Widget
+
+ 中文
+
+ Want to add a Pixiv Daily Ranking Widget to your website? Now, it only takes one line code to do it!
+ DEMO
+
+
+## ✨ Features
+- Easy to use by only one `HTML` code
+- Adaptive width and height. Recommended width `240px`, height `380px` or more
+- Click the image redirect to detail page
+- Automatic daily update
+- Built-in multi image-hosting support, on-demand image loading, extremely low resource consumption
+- Provide API service, including ranking update date, thumbnail url and detail page url, etc.
+
+## 🤔 How to use
+Just add this line to your page
+```html
+
+```
+
+Take `Wordpress` as an example. First go to `wp-admin`, click **Appearance** -> **Widgets**
+Add a **Text** or **Custom HTML** widget to the right in the appropriate place and fill in the above code
+
+[Advance Usage](doc/advance-usage.en.md)
+
+## 🛠️ How to deploy
+Want to customize the code yourself? Think the service I provide is too slow?
+
+You can also easily have your own widget!
+> Requires PHP version >= 5.6
+
+[Deployment Documentation](doc/deploy.en.md)
+
+## 🔌 API
+[Ranking data (already uploaded to the image-hosting)](https://cloud.mokeyjay.com/pixiv/?r=api/pixiv-json) (recommended)
+[Ranking data (pixiv url)](https://cloud.mokeyjay.com/pixiv/?r=api/source-json)
+
+`data` is the ranking data; `date` is the ranking date (maybe yesterday or the day before yesterday, because the official update time is not necessarily)
+
+Both api automatically return the corresponding cross-domain header based on the `Origin` or `Referer` in the request header. They can be called directly by the front-end
+
+> The `image` and `url` keys are for compatibility with users of 4.x and earlier versions, you can ignore them
+
+## 🆙 Upgrade Guide
+1. [Download ZIP](https://github.com/mokeyjay/pixiv-daily-ranking-widget/releases/latest)
+2. Unzip and overwrite the `app` and `index.php` to your server
+
+### From 4.x to 5.0
+1. Check the `image_hosting` item's comment from [config.php](config.php#L90), select the appropriate option and fill it in your `config.php`
+2. Delete all files in 'storage/app', then let the program refresh the ranking data
+
+## 🌟 Changelog
+### Added
+- api service support cross-domain
+- scheduled job to clearing historical logs
+- support 8 free image-hosting
+### Optimization
+- Picture display effect
+- Left and right arrows will auto hidden now
+- Show works title and author name when hovering
+- Upgrade front-end dependency package to the latest, reduce dependency
+- Improve logging function
+- Enrich interface data to fit more scenarios
+- Replace Baidu statistics with Google statistics
+- Update default UA
+### Fix
+- the project url is not correctly retrieved in some cases
+- download invalid picture in some cases
+### Other
+- Remove invalid Alibaba image-hosting
+
+[History](doc/log.en.md)
+
+## 👨💻 About author
+[mokeyjay](https://www.mokeyjay.com), IT and ACG lover
diff --git a/README.md b/README.md
index c810afb..6cba587 100644
--- a/README.md
+++ b/README.md
@@ -1,178 +1,75 @@
-## Pixiv每日排行榜小挂件
-![Pixiv每日排行榜小挂件效果图](https://i.loli.net/2019/05/04/5ccd5293141b4.jpg)
-## 简介
-骚年,你是`ACG`或绘画爱好者吗?你希望在你的博客或网站中添加一个 **`Pixiv`每日排行榜** 的展示功能吗?现在,无需在茫茫互联网中寻找适合自己站点的插件了,只需要几个文件或是一行代码即可实现!
-
-## 特色
-- 一行`HTML`代码即可调用,方便快捷
-- 适合放在大部分博客或网站的侧边栏
-- 自适应宽高。推荐宽度`240px`、高度`380px`
+🖼️ Pixiv 每日排行榜小挂件
+
+ English
+
+ 想要在你的网站页面中添加一个 Pixiv 每日排行榜 的展示功能吗?现在,只需要一行代码即可实现!
+ 在线预览
+
+
+## ✨ 特色
+- 一行 `HTML` 代码即可调用,方便快捷
+- 自适应宽高。推荐宽度 `240px`、高度 `380px` 或以上
- 点击图片可跳转到对应作品详情页
- 每日自动更新,无需人工干预
- 内置多图床支持、按需加载图片,极低资源消耗
-- 提供API服务,含有排行榜更新日期、缩略图url及详情页url
-
-## 开源地址
-[Github](https://github.com/mokeyjay/Pixiv-daily-ranking-widget)
-
-## 如何部署
-### 方案一:使用[超能小紫](https://www.mokeyjay.com)提供的服务
-> 感谢 [rixCloud](https://rixcloud.app/mokeyjay) 提供代理支持
+- 提供 API 服务,含有排行榜更新日期、缩略图 url 及详情页 url 等
-该方案适用于动手能力较差或较懒或没有特殊需求的用户。且已配置数个图床,访问速度较快
-服务地址:[https://cloud.mokeyjay.com/pixiv](https://cloud.mokeyjay.com/pixiv)
-
-以`Wordpress`为例,首先进入 后台 -> 外观 -> 小工具
-向右边适当的位置添加一个 **文本** 或 **自定义HTML** 小工具,标题随意,内容为
+## 🤔 如何使用
+将这行代码添加到网页上即可
```html
-
+
```
-点击保存按钮即可回到博客首页预览效果咯~
-如果你了解`CSS`的话,还可以随意修改`iframe`的`style`属性
-推荐宽度`240px`、高度`380px` (因为P站缩略图最大就是这个尺寸)
-
-#### 自定义背景颜色
-默认为透明背景色,一般情况下不必特意去改背景颜色
-
-如果你还是要改,可以参考下面的示例:
-例如将上面`iframe`的`src`属性的值改为`https://cloud.mokeyjay.com/pixiv/?color=f00`试试看?
-正常情况下背景颜色会变成**红色**,即`#f00`。如果颜色没有改变,可能是缓存问题,刷新几次即可
-`color`的值就是CSS内使用的颜色值,可为3或6位16进制字符。无需 **#** 号
-#### 自定义Top数量
-你还可以通过`limit`参数限制图片数量
-例如`https://cloud.mokeyjay.com/pixiv/?color=f00&limit=10`
-则可以得到背景为红色的Top10画册
-> `limit`参数的范围必须在`1-500` 之间
-
-#### API服务
-[图床缩略图URL+详情页URL](https://cloud.mokeyjay.com/pixiv/storage/app/pixiv.json)(推荐)
-[Pixiv原始缩略图URL+详情页URL](https://cloud.mokeyjay.com/pixiv/storage/app/source.json)
-内容很简单,相信大家看了就知道可以怎么用了,不再赘述
-
-
-### 方案二:自行架设服务
-适用于动手能力较强或需要深度自定义的用户
-> 需要PHP版本 >= 5.4
-
-首先[下载源代码](https://github.com/mokeyjay/Pixiv-daily-ranking-widget/releases/latest),解压
-使用专业编辑器(例如`Sublime`、`Notepad++`等,切忌使用记事本)编辑`config.php`,根据实际情况修改相应配置
-> 由于Pixiv已经被墙,如果你想要将此项目部署在国内,请务必配置 `proxy` 配置项
-
-> 每个配置项的说明都以注释的形式标注在文件内。如果你看不懂,那就说明你比较适合**方案一**
-
-最后一步,给予`storage`目录读写权限
-具体使用方法参考**方案一**
-
-### 注意事项
-- 推荐使用方案一,由我本人维护,如有问题第一时间更新
-- 方案二反馈问题之前,请先将 `log_level` 设为 `['ERROR', 'DEBUG']` ,并再次重现问题后,带着 `logs` 来反馈
-- 本项目免费开源,仅供学习交流。请勿用于任何商业用途,作者不承担任何责任
-
-## 更新日志
-### 4.4.2
-- 更新 Curl 类的默认 UA
-- 删除已经失效的图床
-- 更新阿里巴巴图床
-- 添加 `disable_web_job` 开关,详见 `config.php`
-
-### 4.4.1
-- 更新 Curl 类的默认 UA
-- 修复部分情况下获取项目URL错误
-- 修复获取排行榜数据失败时会无限重试的问题
-- 优化是否需要更新数据的判断机制
-- 删除已经失效的 alibaba 图床
-
-### 4.4
-- 改用官方 ajax 接口获取排行数据
-- 添加 阿里巴巴、百度、今日头条 图床接口
-- 更新 smms 图床接口到 v2 版本
-- 删除已被废弃的 img.sb 图床接口
-- 删除已被封锁的 京东 图床接口
-- 删除 loading 页面的统计代码
-- 改用综合排行榜数据,而非仅限于插画
-- 图片数量限制扩充到 500,达到官方上限
-- service 配置项的取值不再影响 limit
-- 其他优化、bug 修复
-
-### 4.3
-- 修复Pixiv排行榜页面代码改版导致的无法更新
-- 跳转至详情页时使用 https
-
-### 4.2
-- 修复Pixiv排行榜页面代码改版导致的无法更新
-- 添加获取排行榜失败时的最大重试次数
-
-### 4.1
-- 现已支持透明背景
-
-### 4.0
-- 几乎重写了所有代码的船新版本,更多新特性与bug等你来发掘!
-- 由于pixiv全面开启反盗链,为了迎合此变化。已将`download`和`url_cache`这两个不再有存在意义的开关去除。现在会强制下载缩略图,然后再根据配置上传到各个图床或存储在服务器本地
-> 碎碎念:原本这个项目只是随便搞搞,没想到后面功能越堆越多,代码也越来越丑。作为本辣鸡github上最高star的项目实在是丢人。好在我花了几天时间撸了这个4.0,总算是不那么丢人了
-> 还有就是添加了多图床的支持,每个月能节省几百G的流量了嘤
-
-### 3.0
-- 添加`$download_proxy`配置项
-- 由于Pixiv的图片url添加了防盗链无法被直接显示,因此`$download`配置项默认开启
- 为了更好的显示效果,自行部署的用户建议配置一个定时任务,每天0点触发`download.php`
-
-### 2.9
-- 修复因Pixiv改动导致挂掉的问题
-
-### 2.8
-- 尝试优化更新锁,防止高并发下重复更新
-- 从 Conf::$download 中独立出配置项 Conf::$url_cache,现在可以仅缓存图片url而不缓存缩略图了
-- 添加贴图库图床支持
-
-> 贴图库免费版并不是很好用且不支持https,建议优先使用sm.ms,贴图库仅作为备用
-> 由于之前更新锁在高并发下有些问题无法很好的发挥作用,导致我的服务器IP因重复上传被sm.ms图床封了。而我个人也无力支撑高昂的CDN费用。因此即日起**方案一**不再提供CDN加速,改为直接从P站获取图片
-> 方案一目前由360网站卫士提供CDN支持
-
-### 2.7
-- 添加图片压缩功能,降低服务器带宽压力(需要GD库)
-- 修复sm.ms图床支持,降低失败概率
-- 添加sm.ms图床上传日志
-
-> 如果开启`$enable_smms`出现问题,反馈时请带上日志文件
-
-### 2.6
-- 添加sm.ms图床支持。一键启用即可大幅降低服务器带宽压力、节省流量。感谢[@Showfom](https://sb.sb/)提供图床
-
-> 我才不告诉你是因为方案一每天跑掉我几G流量,心疼不已才加的这个功能呢
-> 如果连续3次上传失败,则从服务器本地读取图片,确保访问正常
-
-### 2.5
-- 修复因Pixiv改版导致挂掉的问题
-- Pixiv原生支持https啦!可喜可贺
-
-### 2.4
-- 修复特定情况下URL的`limit`参数无效的问题
-- 修复**方案一**缓存问题
-- 修复上面效果图SSL证书问题
-
-### 2.3
-- 更换了前端库引用地址,修复移动宽带下加载慢的问题
-- 添加协议自适应,修复在关闭缓存或缓存还没全部完成时影响小绿锁的问题
-- 以上更新来自@灵乌路空 的友情PR,我们一起对她PRPR以示感激吧
-- 超能小紫的方案一服务现已支持HTTPS。咬牙忍痛上了收费CDN,请大家且用且珍惜
-- 要是被滥用到我吃不消费用的话可能会暂停服务噢~
-- 如果访问量较高的话建议还是自行搭建服务,谢谢各位的支持与谅解
-
-### 2.2
-- 优化下载线程以支持自行部署HTTPS
-
-### 2.1
-- 规划2.0时脑子抽了,非要把所有逻辑都局限在一个文件里。虽然各方面确实有所提升,但在一些情况下照样会出现那些老问题。例如缩略图下载失败啊、PHP超时导致下载中断之类。因此在我测试并意识到这一点时,赶紧开始了新版本的开发 光速打脸
-- 去除自动更新锁机制,缩略图已存在并且有效时不再重复下载。防止因网络波动或超时导致的缩略图下载失败
-
-### 2.0
-- 整体重构,各机制大幅优化
-- 添加自动更新锁机制,避免高访问量时并发更新浪费资源
-- 全新的伪多线程自动更新机制,后台更新不影响使用
-- 更新失败重试,避免因为网络问题导致的部分图片获取失败
-
-## 初衷
-前几天跟朋友聊天,朋友说希望能在自己博客侧边栏中显示[Pixiv](http://www.pixiv.net/)的每日排行榜。我自己也是个`ACG`爱好者,被他这么一说也想弄一个。昨晚终于有空,花了半个多小时写完。[自己博客](https://www.mokeyjay.com)用上了感觉不错,完善了一下加了点功能开源出来福利各位
-## 关于作者
-[超能小紫](https://www.mokeyjay.com),常用ID`mokeyjay`。热爱IT与ACG的学渣
\ No newline at end of file
+以 `Wordpress` 为例。首先进入后台,点击 外观 -> 小工具
+向右边适当的位置添加一个 **文本** 或 **自定义HTML** 小工具,内容填写上述代码即可
+
+[高级用法](doc/advance-usage.md)
+
+## 🛠️ 如何部署
+想要自己定制代码?嫌我提供的服务太慢?
+你也可以轻松拥有完全属于自己的小挂件!
+> 需要 PHP 版本 >= 5.6
+
+[部署文档](doc/deploy.md)
+
+## 🔌 API
+[排行榜数据(已上传至图床)](https://cloud.mokeyjay.com/pixiv/?r=api/pixiv-json)(推荐)
+[排行榜数据(pixiv url)](https://cloud.mokeyjay.com/pixiv/?r=api/source-json)
+
+其中 `data` 为排行榜数据;`date` 为排行榜日期(可能是昨天或者前天,因为官方更新时间不一定)
+这两个接口都会自动根据请求头的 `Origin` 或者 `Referer` 返回对应跨域头。可供前端直接调用
+
+> `image` 和 `url` 两个键是为了兼容 4.x 及之前版本的用户,无需理会
+
+## 🆙 升级指南
+1. [下载源代码](https://github.com/mokeyjay/Pixiv-daily-ranking-widget/releases/latest)
+2. 解压缩,将其中的 `app` 和 `index.php` 覆盖到线上环境
+
+### 从 4.x 升级到 5.0
+1. 查看 [config.php](config.php#L90) 中 `image_hosting` 配置项的注释说明,选择适合你的图床配置,填写到你线上环境的 `config.php` 中
+2. 删除 `storage/app` 下的所有文件,让程序重新获取排行榜数据
+
+## 🌟 更新日志
+### 新增
+- 支持跨域请求的数据接口
+- clear-log 任务用于清除历史日志文件
+- 共计 8 个国内外公开、免费的图床
+### 优化
+- 图片显示效果
+- 左右翻页箭头现在会自动隐藏了
+- 鼠标悬浮时显示作品标题及作者名称
+- 升级前端依赖包至最新、减少依赖
+- 完善日志记录功能
+- 丰富接口数据以适应更多场景
+- 将百度统计更换为谷歌统计
+- 更新默认 UA
+### 修复
+- 部分情况下无法正确获取项目 url 的问题
+- 部分情况下可能会下载到空白图片的问题
+### 其他
+- 去掉失效的阿里巴巴图床
+
+[历史更新日志](doc/log.md)
+
+## 👨💻 关于作者
+常用 ID [mokeyjay](https://www.mokeyjay.com),热爱 IT 与 ACG 的学渣
\ No newline at end of file
diff --git a/app/App.php b/app/App.php
index 676dad5..0595b19 100644
--- a/app/App.php
+++ b/app/App.php
@@ -4,10 +4,8 @@
use app\Jobs\Job;
use app\Libs\Config;
-use app\Libs\Lock;
-use app\Libs\Pixiv;
-use app\Libs\Storage;
-use app\Libs\Tools;
+use app\Libs\Log;
+use app\Libs\Str;
class App
{
@@ -19,8 +17,8 @@ protected static function init()
Config::init();
// 注册全局错误捕捉
- set_exception_handler(function (\Exception $exception) {
- Tools::log($exception->getMessage(), 'ERROR');
+ set_exception_handler(function ($exception) {
+ Log::write($exception->getMessage(), 'ERROR');
http_response_code(500);
die;
});
@@ -30,11 +28,7 @@ public static function run()
{
self::init();
- $opt = getopt('j:');
- if (!empty($_GET['job']) || isset($opt['j'])) {
- self::job();
- return;
- }
+ self::job();
self::route();
}
@@ -46,33 +40,59 @@ public static function run()
protected static function job()
{
$opt = getopt('j:');
- $jobName = isset($_GET['job']) ? $_GET['job'] : $opt['j'];
- $jobName = ucfirst(strtolower($jobName));
+ if (empty($_GET['job']) && empty($opt['j'])) {
+ return;
+ }
+
+ $jobName = !empty($_GET['job']) ? $_GET['job'] : $opt['j'];
$job = Job::make($jobName);
+
+ if (!empty($_GET['job']) && $job->onlyActivateByCli) {
+ throw new \Exception("任务 {$jobName} 只能通过 cli 触发");
+ }
+
if (!$job) {
throw new \Exception("任务 {$jobName} 加载失败");
}
set_time_limit(0);
if ($job->run()) {
- Tools::log("任务 {$jobName} 执行完毕");
+ Log::write("任务 {$jobName} 执行完毕");
echo "任务 {$jobName} 执行完毕";
} else {
throw new \Exception("任务 {$jobName} 执行失败:{$job->getErrorMsg()}");
}
+
+ exit;
}
/**
- * 调用控制器
+ * 路由
*/
protected static function route()
{
$route = isset($_GET['r']) ? $_GET['r'] : 'index';
$route = explode('/', $route);
- $method = array_pop($route) ?: 'index';
- $controller = 'app\\Controllers\\' . ucfirst(array_pop($route) ?: 'index') . 'Controller';
+ $controller = Str::studly(array_shift($route) ?: 'index');
+ $method = lcfirst(Str::studly(array_pop($route) ?: 'index'));
+
+ $class = "app\\Controllers\\{$controller}Controller";
+ if (!class_exists($class)) {
+ Log::write("控制器不存在:{$class}", Log::LEVEL_ERROR);
+
+ http_response_code(404);
+ die;
+ }
+
+ $controller = new $class;
+ if (!is_callable([$controller, $method])) {
+ Log::write("无法调用此方法:{$class}->{$method}()", Log::LEVEL_ERROR);
+
+ http_response_code(404);
+ die;
+ }
- (new $controller)->$method();
+ $controller->$method();
}
}
\ No newline at end of file
diff --git a/app/Controllers/ApiController.php b/app/Controllers/ApiController.php
new file mode 100644
index 0000000..81a1f65
--- /dev/null
+++ b/app/Controllers/ApiController.php
@@ -0,0 +1,51 @@
+setAutoCorsHeader();
+ }
+
+ /**
+ * 自动设置跨域头
+ * @return void
+ */
+ private function setAutoCorsHeader()
+ {
+ if (!isset($_SERVER['HTTP_ORIGIN']) && !isset($_SERVER['HTTP_REFERER'])) {
+ return;
+ }
+
+ $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : $_SERVER['HTTP_REFERER'];
+
+ header('Access-Control-Allow-Origin: ' . $origin);
+ }
+
+ /**
+ * 源数据(未使用图床)
+ * @return void
+ */
+ public function sourceJson()
+ {
+ echo json_encode(Storage::getJson('source') ?: []);
+ }
+
+ /**
+ * 处理后的数据(已使用图床)
+ * @return void
+ */
+ public function pixivJson()
+ {
+ echo json_encode(Storage::getJson('pixiv') ?: []);
+ }
+}
\ No newline at end of file
diff --git a/app/Controllers/IndexController.php b/app/Controllers/IndexController.php
index 5d5b215..24ab713 100644
--- a/app/Controllers/IndexController.php
+++ b/app/Controllers/IndexController.php
@@ -5,8 +5,8 @@
use app\Libs\Config;
use app\Libs\Lock;
use app\Libs\Pixiv;
+use app\Libs\Request;
use app\Libs\Storage;
-use app\Libs\Tools;
class IndexController extends Controller
{
@@ -15,7 +15,7 @@ public function index()
$pixivJson = Storage::getJson('pixiv');
if ($pixivJson === false || !Pixiv::checkDate($pixivJson)) {
if (Lock::create('refresh', 600) && Config::$disable_web_job === false) {
- Tools::runRefreshThread();
+ Request::execRefreshThread();
}
}
diff --git a/app/ImageHosting/Alibaba.php b/app/ImageHosting/Alibaba.php
deleted file mode 100644
index d808492..0000000
--- a/app/ImageHosting/Alibaba.php
+++ /dev/null
@@ -1,39 +0,0 @@
- Curl::getCurlFile($path),
- 'scene' => 'aeMessageCenterImageRule',
- 'name' => 'image.jpg'
- ];
- $result = Curl::post('https://kfupload.alibaba.com/mupload', $data, [
- CURLOPT_USERAGENT => 'iAliexpress/8.25.0 (iPhone; iOS 14.5; Scale/3.00)',
- ]);
-
- Tools::log('[阿里巴巴图床]上传:' . json_encode($data));
- Tools::log('[阿里巴巴图床]返回:' . $result);
-
- $json = json_decode($result, true);
- if(isset($json['code']) && $json['code'] == 0 && isset($json['url'])){
- return $json['url'];
- }
-
- Tools::log('[阿里巴巴图床]上传失败', 'ERROR');
- return false;
- }
-}
\ No newline at end of file
diff --git a/app/ImageHosting/Baidu.php b/app/ImageHosting/Baidu.php
index a325925..c013a8b 100644
--- a/app/ImageHosting/Baidu.php
+++ b/app/ImageHosting/Baidu.php
@@ -3,7 +3,7 @@
namespace app\ImageHosting;
use app\Libs\Curl;
-use app\Libs\Tools;
+use app\Libs\Log;
/**
* 百度图床
@@ -31,15 +31,15 @@ public function upload($path)
],
]);
- Tools::log('[百度图床]上传:' . json_encode($data));
- Tools::log('[百度图床]返回:' . $result);
+ Log::write('[百度图床]上传:' . json_encode($data));
+ Log::write('[百度图床]返回:' . $result);
$json = json_decode($result, true);
if(isset($json['errno']) && $json['errno'] == 0 && isset($json['ret']['org_url'])){
return $json['ret']['org_url'];
}
- Tools::log('[百度图床]上传失败', 'ERROR');
+ Log::write('[百度图床]上传失败', 'ERROR');
return false;
}
}
\ No newline at end of file
diff --git a/app/ImageHosting/Catbox.php b/app/ImageHosting/Catbox.php
new file mode 100644
index 0000000..04d3cc9
--- /dev/null
+++ b/app/ImageHosting/Catbox.php
@@ -0,0 +1,35 @@
+ 'fileupload',
+ 'userhash' => '',
+ 'fileToUpload' => Curl::getCurlFile($path),
+ ];
+ $result = Curl::post('https://catbox.moe/user/api.php', $data);
+
+ Log::write('[猫盒图床]上传:' . json_encode($data));
+ Log::write('[猫盒图床]返回:' . $result);
+
+ if (stripos($result, 'files.catbox.moe') !== false) {
+ return $result;
+ }
+
+ Log::write('[猫盒图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/ImageHosting/Chkaja.php b/app/ImageHosting/Chkaja.php
new file mode 100644
index 0000000..4dc061a
--- /dev/null
+++ b/app/ImageHosting/Chkaja.php
@@ -0,0 +1,41 @@
+ Curl::getCurlFile($path),
+ 'viewpassword' => '',
+ 'viewtips' => '',
+ 'Timelimit' => '',
+ 'Countlimit' => '',
+ 'submit' => 'submit',
+ 'MAX_FILE_SIZE' => '8388608',
+ ];
+ $result = Curl::post('https://img.chkaja.com/ajaximg.php', $data);
+
+ Log::write('[愛上傳图床]上传:' . json_encode($data));
+ Log::write('[愛上傳图床]返回:' . $result);
+
+ $url = preg_match('|https://img.chkaja.com/(.*?)\.jpg|', $result, $matches) ? $matches[0] : false;
+
+ if (!empty($url)) {
+ return $url;
+ }
+
+ Log::write('[愛上傳图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/ImageHosting/ImageHosting.php b/app/ImageHosting/ImageHosting.php
index d36d16b..7502238 100644
--- a/app/ImageHosting/ImageHosting.php
+++ b/app/ImageHosting/ImageHosting.php
@@ -3,6 +3,7 @@
namespace app\ImageHosting;
use app\Factory;
+use app\Libs\Str;
/**
* 抽象 图床类
@@ -18,7 +19,7 @@ abstract class ImageHosting extends Factory
*/
public static function make($name, array $config = [])
{
- $name = '\\app\\ImageHosting\\' . ucfirst(strtolower($name));
+ $name = '\\app\\ImageHosting\\' . Str::studly($name);
return parent::make($name, $config);
}
diff --git a/app/ImageHosting/Imgstop.php b/app/ImageHosting/Imgstop.php
new file mode 100644
index 0000000..4743ed8
--- /dev/null
+++ b/app/ImageHosting/Imgstop.php
@@ -0,0 +1,51 @@
+ Curl::getCurlFile($path),
+ // 7=携程 15=易车,随机选一个
+ 'strategy_id' => [7, 15][mt_rand(0, 1)],
+ ];
+ $opt = [
+ CURLOPT_HTTPHEADER => [
+ 'x-csrf-token: ' . $csrfToken,
+ ],
+ CURLOPT_COOKIE => $result['cookie'],
+ ];
+ $result = Curl::post('https://imgs.top/upload', $data, $opt);
+
+ Log::write('[映画の图床]上传:' . json_encode(compact('data', 'opt')));
+ Log::write('[映画の图床]返回:' . $result);
+
+ $json = json_decode($result, true);
+ if (!empty($json['data']['imgurl'])) {
+ return $json['data']['imgurl'];
+ }
+
+ Log::write('[映画の图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/ImageHosting/Imgtg.php b/app/ImageHosting/Imgtg.php
new file mode 100644
index 0000000..ecbf46b
--- /dev/null
+++ b/app/ImageHosting/Imgtg.php
@@ -0,0 +1,54 @@
+ Curl::getCurlFile($path),
+ 'type' => 'file',
+ 'action' => 'upload',
+ 'timestamp' => substr(microtime(true) * 1000, 0, 13),
+ 'auth_token' => $authToken,
+ 'nsfw' => '0',
+ ];
+ $result = Curl::post('https://imgtg.com/json', $data, [
+ CURLOPT_HTTPHEADER => [
+ 'accept: application/json',
+ 'referer: https://imgtg.com',
+ 'origin: https://imgtg.com',
+ ],
+ CURLOPT_COOKIE => $result['cookie'],
+ ]);
+
+ Log::write('[Imgtg 图床]上传:' . json_encode($data));
+ Log::write('[Imgtg 图床]返回:' . $result);
+
+ $json = json_decode($result, true);
+ if(!empty($json['image']['image']['url'])){
+ return $json['image']['image']['url'];
+ }
+
+ Log::write('[Imgtg 图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/ImageHosting/Imgurl.php b/app/ImageHosting/Imgurl.php
new file mode 100644
index 0000000..8ee2cd9
--- /dev/null
+++ b/app/ImageHosting/Imgurl.php
@@ -0,0 +1,34 @@
+ Curl::getCurlFile($path),
+ ];
+ $result = Curl::post('https://www.imgurl.org/upload/aws_s3', $data);
+
+ Log::write('[Imgurl 图床]上传:' . json_encode($data));
+ Log::write('[Imgurl 图床]返回:' . $result);
+
+ $json = json_decode($result, true);
+ if (!empty($json['url'])) {
+ return $json['url'];
+ }
+
+ Log::write('[Imgurl 图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/ImageHosting/Local.php b/app/ImageHosting/Local.php
index 1390d0a..1f8a2db 100644
--- a/app/ImageHosting/Local.php
+++ b/app/ImageHosting/Local.php
@@ -3,7 +3,7 @@
namespace app\ImageHosting;
use app\Libs\Config;
-use app\Libs\Tools;
+use app\Libs\Log;
/**
* 本地存储
@@ -17,13 +17,14 @@ public function upload($path)
{
$fileName = pathinfo($path, PATHINFO_BASENAME);
$file = STORAGE_PATH . 'images/' . $fileName;
- Tools::log('[本地]目标:' . $path);
- Tools::log('[本地]存储到:' . $file);
+ Log::write('[本地]目标:' . $path);
+ Log::write('[本地]存储到:' . $file);
- if (file_put_contents($file, file_get_contents($path)) === false) {
- Tools::log('[本地]存储失败', 'ERROR');
+ if (!file_put_contents($file, file_get_contents($path))) {
+ Log::write('[本地]存储失败', 'ERROR');
return false;
}
+
return Config::$url . 'storage/images/' . $fileName;
}
}
\ No newline at end of file
diff --git a/app/ImageHosting/Pngcm.php b/app/ImageHosting/Pngcm.php
new file mode 100644
index 0000000..f97960a
--- /dev/null
+++ b/app/ImageHosting/Pngcm.php
@@ -0,0 +1,37 @@
+ Curl::getCurlFile($path),
+ 'name' => pathinfo($path, PATHINFO_BASENAME),
+ 'uuid' => 'o_1g840' . Str::random(21),
+ ];
+ $result = Curl::post('https://png.cm/application/upload.php', $data);
+
+ Log::write('[Pngcm 图床]上传:' . json_encode($data));
+ Log::write('[Pngcm 图床]返回:' . $result);
+
+ $json = json_decode($result, true);
+ if (isset($json['code']) && $json['code'] == 200 && !empty($json['url'])) {
+ return $json['url'];
+ }
+
+ Log::write('[Pngcm 图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/ImageHosting/Saoren.php b/app/ImageHosting/Saoren.php
new file mode 100644
index 0000000..f647a6c
--- /dev/null
+++ b/app/ImageHosting/Saoren.php
@@ -0,0 +1,37 @@
+ Curl::getCurlFile($path),
+ 'name' => pathinfo($path, PATHINFO_BASENAME),
+ 'uuid' => 'o_1g840' . Str::random(21),
+ ];
+ $result = Curl::post('https://tu.sao.ren/file.php', $data);
+
+ Log::write('[骚人图床]上传:' . json_encode($data));
+ Log::write('[骚人图床]返回:' . $result);
+
+ $json = json_decode($result, true);
+ if (isset($json['code']) && $json['code'] == 200 && !empty($json['url'])) {
+ return $json['url'];
+ }
+
+ Log::write('[骚人图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/ImageHosting/Smms.php b/app/ImageHosting/Smms.php
index bcb0a4c..a1fddeb 100644
--- a/app/ImageHosting/Smms.php
+++ b/app/ImageHosting/Smms.php
@@ -4,7 +4,7 @@
use app\Libs\Config;
use app\Libs\Curl;
-use app\Libs\Tools;
+use app\Libs\Log;
/**
* sm.ms图床
@@ -18,7 +18,7 @@ class Smms extends ImageHosting
public function upload($path)
{
if (empty(Config::$image_hosting_extend['smms']['token'])) {
- Tools::log('[Smms图床]上传失败:请先配置 smms 的 token', 'ERROR');
+ Log::write('[Smms图床]上传失败:请先配置 smms 的 token', 'ERROR');
return false;
}
@@ -30,8 +30,8 @@ public function upload($path)
];
$result = Curl::post('https://sm.ms/api/v2/upload', $data, $header);
- Tools::log('[Smms图床]上传:' . json_encode($data));
- Tools::log('[Smms图床]返回:' . $result);
+ Log::write('[Smms图床]上传:' . json_encode($data));
+ Log::write('[Smms图床]返回:' . $result);
$result = json_decode($result, true);
if (isset($result['code'])) {
@@ -42,7 +42,7 @@ public function upload($path)
}
}
- Tools::log('[Smms图床]上传失败:' . $result['msg'], 'ERROR');
+ Log::write('[Smms图床]上传失败:' . $result['msg'], 'ERROR');
return false;
}
}
\ No newline at end of file
diff --git a/app/ImageHosting/Tietuku.php b/app/ImageHosting/Tietuku.php
index b21994a..8bdf159 100644
--- a/app/ImageHosting/Tietuku.php
+++ b/app/ImageHosting/Tietuku.php
@@ -4,7 +4,7 @@
use app\Libs\Config;
use app\Libs\Curl;
-use app\Libs\Tools;
+use app\Libs\Log;
/**
* tietuku图床
@@ -18,7 +18,7 @@ class Tietuku extends ImageHosting
public function upload($path)
{
if (empty(Config::$image_hosting_extend['tietuku']['token'])) {
- Tools::log('[Tietuku图床]上传失败:请先配置 tietuku 的 token', 'ERROR');
+ Log::write('[Tietuku图床]上传失败:请先配置 tietuku 的 token', 'ERROR');
return false;
}
@@ -28,12 +28,12 @@ public function upload($path)
];
$result = Curl::post('http://up.imgapi.com/', $data);
- Tools::log('[Tietuku图床]上传:' . json_encode($data));
- Tools::log('[Tietuku图床]返回:' . $result);
+ Log::write('[Tietuku图床]上传:' . json_encode($data));
+ Log::write('[Tietuku图床]返回:' . $result);
$result = json_decode($result, true);
if (isset($result['code'])) {
- Tools::log('[Tietuku图床]上传失败:' . $result['info'], 'ERROR');
+ Log::write('[Tietuku图床]上传失败:' . $result['info'], 'ERROR');
return false;
}
return $result['linkurl'];
diff --git a/app/ImageHosting/Tsesze.php b/app/ImageHosting/Tsesze.php
new file mode 100644
index 0000000..94b6574
--- /dev/null
+++ b/app/ImageHosting/Tsesze.php
@@ -0,0 +1,34 @@
+ Curl::getCurlFile($path),
+ ];
+ $result = Curl::post('https://www.268608.com/upload/localhost', $data);
+
+ Log::write('[Tsesze 图床]上传:' . json_encode($data));
+ Log::write('[Tsesze 图床]返回:' . $result);
+
+ $json = json_decode($result, true);
+ if (!empty($json['url'])) {
+ return $json['url'];
+ }
+
+ Log::write('[Tsesze 图床]上传失败', 'ERROR');
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/app/Jobs/ClearLog.php b/app/Jobs/ClearLog.php
new file mode 100644
index 0000000..3affee4
--- /dev/null
+++ b/app/Jobs/ClearLog.php
@@ -0,0 +1,42 @@
+ 0 && is_numeric($opt['n'])) ? intval($opt['n']) : 7;
+
+ $time = strtotime("-{$n} days");
+ $path = STORAGE_PATH . 'logs/';
+ $deleteNum = 0;
+
+ if ($dh = opendir($path)) {
+ while (($file = readdir($dh)) !== false) {
+ if (in_array($file, ['.', '..', '.gitignore'])) {
+ continue;
+ }
+
+ $file = $path . $file;
+ if (filemtime($file) < $time) {
+ $deleteNum++;
+ Storage::deleteFile($file);
+ }
+ }
+ }
+
+ Log::write("共计清除日志文件 {$deleteNum} 个");
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/app/Jobs/Job.php b/app/Jobs/Job.php
index 9cf94e0..24b7c7c 100644
--- a/app/Jobs/Job.php
+++ b/app/Jobs/Job.php
@@ -3,6 +3,7 @@
namespace app\Jobs;
use app\Factory;
+use app\Libs\Str;
/**
* 抽象 任务类
@@ -11,6 +12,9 @@
*/
abstract class Job extends Factory
{
+ // 是否只能通过 cli 触发
+ public $onlyActivateByCli = false;
+
/**
* @param string $name
* @param array $config
@@ -18,7 +22,7 @@ abstract class Job extends Factory
*/
public static function make($name, array $config = [])
{
- $name = '\\app\\Jobs\\' . ucfirst(strtolower($name));
+ $name = '\\app\\Jobs\\' . Str::studly($name);
return parent::make($name, $config);
}
diff --git a/app/Jobs/Refresh.php b/app/Jobs/Refresh.php
index e6e54cb..ee38585 100644
--- a/app/Jobs/Refresh.php
+++ b/app/Jobs/Refresh.php
@@ -1,147 +1,160 @@
-needRefresh($ranking, $pixivJson)){
- Tools::log('排行榜尚未更新,半小时后再试');
- Lock::forceCreate('refresh', 1800);
- return true;
- }
-
- $images = Pixiv::getImages();
- if($images === false) {
- throw new \Exception('【致命错误】无法获取Pixiv排行榜图片列表');
- }
-
- $pixivJson = [
- 'image' => [],
- 'url' => [],
- ];
-
- $enableCompress = Config::$compress && function_exists('imagecreatefromjpeg');
-
- $imageHostingInstances = [];
- foreach (Config::$image_hosting as $ihName) {
- $imageHostingInstances[] = ImageHosting::make($ihName);
- }
-
- $proxy = Config::$proxy;
-
- // 开始获取图片
- foreach ($images['image'] as $i => $imageUrl) {
- // 缓存数量限制
- if ($i >= Config::$limit) {
- break;
- }
- // 最多尝试下载3次
- Config::$proxy = $proxy;
- for ($ii = 1; $ii <= 3; $ii++) {
- $tmpfile = Pixiv::downloadImage($imageUrl);
- if ($tmpfile) {
- break;
- } else {
- Tools::log("图片 {$imageUrl} 下载失败,重试第 {$ii} 次");
- sleep(3);
- }
- }
- if (!$tmpfile) {
- throw new \Exception("图片 {$imageUrl} 下载失败");
- }
- // 压缩图片
- if ($enableCompress) {
- $image = imagecreatefromjpeg($tmpfile);
- if ($image) {
- imagejpeg($image, $tmpfile, 95);
- imagedestroy($image);
- unset($image);
- }
- }
- // 上传到图床
- Config::$proxy = null;
- foreach ($imageHostingInstances as $imageHosting) {
- $url = $imageHosting->upload($tmpfile);
- if ($url != false) {
- Storage::deleteFile($tmpfile);
- break;
- }
- }
-
- $pixivJson['image'][] = $url ?: $images['image'][$i]; // 如上传失败则使用原图url(虽然原图url也显示不出来)
- $pixivJson['url'][] = $images['url'][$i];
- }
-
- $pixivJson['date'] = $images['date'];
- Storage::saveJson('pixiv', $pixivJson);
- Lock::remove('refresh');
-
- Config::$clear_overdue && Storage::clearOverdueImages();
- return true;
-
- } catch (\Exception $e) {
-
- // 是否超过最大重试次数
- $refreshCount = (int)Storage::get('refreshCount');
- if ($refreshCount > 10) {
- // 超过10次(5小时)都无法获取到pixiv排行榜
- // 直接锁定一整天,明天再试,降低无意义的资源损耗
- $expire = mktime(23, 59, 59) - time();
- Lock::forceCreate('refresh', $expire);
- Storage::remove('refreshCount');
- } else {
- // 半小时后再试
- Lock::forceCreate('refresh', 1800);
- Storage::save('refreshCount', $refreshCount + 1);
- }
-
- $this->errorMsg = $e->getMessage();
- return false;
- }
- }
-
- /**
- * 是否需要刷新数据
- * @param array $ranking pixiv 接口返回的排行榜数据
- * @param array $pixivJson pixiv.json 的内容
- * @return bool
- * @throws \Exception
- */
- private function needRefresh($ranking, $pixivJson)
- {
- if (!isset($pixivJson['date'])) {
- return true;
- }
-
- // $ranking['date'] 的格式为 20200310
- if ($ranking && isset($ranking['date']) && preg_match('|^\d{8}$|', $ranking['date'])) {
-
- return $pixivJson['date'] != date('Y-m-d', strtotime($ranking['date']));
- }
-
- throw new \Exception('排行榜日期数据异常!数据:' . json_encode($ranking));
- }
+needRefresh($ranking, $pixivJson)){
+ Log::write('排行榜尚未更新,半小时后再试');
+ Lock::forceCreate('refresh', 1800);
+
+ return true;
+ }
+
+ $images = Pixiv::getImages();
+ if($images === false) {
+ throw new \Exception('【致命错误】无法获取Pixiv排行榜图片列表');
+ }
+
+ $enableCompress = Config::$compress && function_exists('imagecreatefromjpeg');
+
+ $imageHostingInstances = [];
+ foreach (Config::$image_hosting as $ihName) {
+ $imageHostingInstances[] = ImageHosting::make($ihName);
+ }
+
+ $proxy = Config::$proxy;
+
+ // 开始获取图片
+ $pixivJson = [];
+ foreach ($images['data'] as $i => $data) {
+ // 缓存数量限制
+ if ($i >= Config::$limit) {
+ break;
+ }
+
+ Log::write("开始获取第 " . ($i + 1) . " 张图:{$data['url']}");
+
+ // 最多尝试下载 3 次
+ Config::$proxy = $proxy;
+ for ($ii = 1; $ii <= 3; $ii++) {
+ $tmpfile = Pixiv::downloadImage($data['url']);
+ if ($tmpfile && getimagesize($tmpfile)) {
+ break;
+ } else {
+ Log::write("图片 {$data['url']} 下载失败,重试第 {$ii} 次");
+ sleep(mt_rand(3, 30));
+ }
+ }
+ if (!$tmpfile) {
+ throw new \Exception("图片 {$data['url']} 下载失败");
+ }
+
+ // 压缩图片
+ if ($enableCompress) {
+ $image = imagecreatefromjpeg($tmpfile);
+ if ($image) {
+ imagejpeg($image, $tmpfile, 95);
+ $bytes = filesize($tmpfile);
+ Log::write('压缩后图片大小: ' . $bytes . ' 字节');
+ imagedestroy($image);
+ unset($image);
+ }
+
+ if ($bytes < 1000) {
+ throw new \Exception("图片 {$data['url']} 下载失败");
+ }
+ }
+
+ // 上传到图床
+ Config::$proxy = null; // 上传过程中禁用代理
+ foreach ($imageHostingInstances as $imageHosting) {
+ $url = $imageHosting->upload($tmpfile);
+ if ($url != false) {
+ Storage::deleteFile($tmpfile);
+ break;
+ }
+ }
+
+ $url = $url ?: $data['url']; // 如上传失败则使用原图url(虽然原图url也显示不出来)
+ $data['url'] = $url;
+
+ $pixivJson['data'][] = $data;
+ $pixivJson['image'][] = $url;
+ $pixivJson['url'][] = "artworks/{$data['id']}";
+ }
+
+ $pixivJson['date'] = $images['date'];
+ Storage::saveJson('pixiv', $pixivJson);
+ Lock::remove('refresh');
+
+ Config::$clear_overdue && Storage::clearOverdueImages();
+
+ return true;
+
+ } catch (\Exception $e) {
+
+ // 是否超过最大重试次数
+ $refreshCount = (int)Storage::get('refreshCount');
+ if ($refreshCount > 10) {
+ // 超过 10 次(5小时)都无法获取到 pixiv 排行榜
+ // 直接锁定一整天,明天再试,降低无意义的资源损耗
+ $expire = mktime(23, 59, 59) - time();
+ Lock::forceCreate('refresh', $expire);
+ Storage::remove('refreshCount');
+ } else {
+ // 半小时后再试
+ Lock::forceCreate('refresh', 1800);
+ Storage::save('refreshCount', $refreshCount + 1);
+ }
+
+ $this->errorMsg = $e->getMessage();
+ return false;
+ }
+ }
+
+ /**
+ * 是否需要刷新数据
+ * @param array $ranking pixiv 接口返回的排行榜数据
+ * @param array $pixivJson pixiv.json 的内容
+ * @return bool
+ * @throws \Exception
+ */
+ private function needRefresh($ranking, $pixivJson)
+ {
+ if (!isset($pixivJson['date'])) {
+ return true;
+ }
+
+ // $ranking['date'] 的格式为 20200310
+ if ($ranking && isset($ranking['date']) && preg_match('|^\d{8}$|', $ranking['date'])) {
+
+ return $pixivJson['date'] != date('Y-m-d', strtotime($ranking['date']));
+ }
+
+ throw new \Exception('排行榜日期数据异常!数据:' . json_encode($ranking));
+ }
}
\ No newline at end of file
diff --git a/app/Libs/Config.php b/app/Libs/Config.php
index 519bc07..0fcae11 100644
--- a/app/Libs/Config.php
+++ b/app/Libs/Config.php
@@ -35,7 +35,7 @@ public static function init()
// 获取本项目url
if (self::$url == '' && !IS_CLI) {
- self::$url = Tools::getCurrentURL();
+ self::$url = Request::getCurrentUrl();
}
// 是否对外提供服务,是则获取url参数
@@ -48,23 +48,25 @@ public static function init()
}
}
- Config::$image_hosting = (array)Config::$image_hosting;
-
try {
if (!is_writable(STORAGE_PATH)) {
throw new \Exception(STORAGE_PATH . ' 目录无法写入');
}
+ if (!is_array(Config::$image_hosting) || count(Config::$image_hosting) < 1) {
+ throw new \Exception('image_hosting 配置项至少要有一个值');
+ }
+
if (self::$limit < 1) {
throw new \Exception('limit 配置项不得小于1');
}
if (IS_CLI && self::$url == '' && in_array('local', self::$image_hosting)) {
- throw new \Exception('在cli模式下使用local本地图床时,必须配置url项,否则可能会生成错误的缩略图url');
+ throw new \Exception('在 cli 模式下使用 local 本地图床时,必须配置 url 项,否则可能会生成错误的缩略图 url');
}
} catch (\Exception $e) {
- Tools::log($e->getMessage(), 'ERROR');
+ Log::write($e->getMessage(), Log::LEVEL_ERROR);
echo '错误:' . $e->getMessage();
die;
diff --git a/app/Libs/Curl.php b/app/Libs/Curl.php
index dea2127..49db94b 100644
--- a/app/Libs/Curl.php
+++ b/app/Libs/Curl.php
@@ -13,9 +13,10 @@ class Curl
* get请求
* @param string $url 请求目标
* @param array $opt curl参数
- * @return bool|string
+ * @param bool $includeCookie 同时返回 cookie
+ * @return bool|string|array $includeCookie 为 true 时返回 ['cookie' => '', 'html' => ''] 数组
*/
- public static function get($url, $opt = [])
+ public static function get($url, $opt = [], $includeCookie = false)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -23,10 +24,10 @@ public static function get($url, $opt = [])
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
- curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36 Edg/91.0.864.48');
- if (Config::$proxy) {
- curl_setopt($ch, CURLOPT_PROXY, Config::$proxy);
- }
+ curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.49');
+
+ Config::$proxy && curl_setopt($ch, CURLOPT_PROXY, Config::$proxy);
+ $includeCookie && curl_setopt($ch, CURLOPT_HEADER, true);
if (count($opt)) {
curl_setopt_array($ch, $opt);
@@ -34,14 +35,35 @@ public static function get($url, $opt = [])
$data = curl_exec($ch);
curl_close($ch);
+
+ if ($includeCookie) {
+ $data = explode("\r\n\r\n", $data);
+
+ $header = array_shift($data);
+ $html = implode("\r\n\r\n", $data);
+
+ preg_match_all("/set\-cookie:([^\r\n]*)/i", $header, $matches);
+
+ $cookie = '';
+ if (!empty($matches[1])) {
+ $cookieItem = [];
+ foreach ($matches[1] as $item) {
+ $cookieItem[] = explode(';', trim($item))[0];
+ }
+ $cookie = implode('; ', $cookieItem);
+ }
+
+ return compact('cookie', 'html');
+ }
+
return $data;
}
/**
* post请求
- * @param string $url
- * @param array $postData
- * @param array $opt
+ * @param string $url
+ * @param array|string $postData
+ * @param array $opt
* @return bool|string
*/
public static function post($url, $postData, $opt = [])
diff --git a/app/Libs/Log.php b/app/Libs/Log.php
new file mode 100644
index 0000000..0dd586e
--- /dev/null
+++ b/app/Libs/Log.php
@@ -0,0 +1,36 @@
+ {$message}\n";
+ if (IS_CLI) {
+ echo $content . "\n";
+ }
+
+ $file = STORAGE_PATH . 'logs/' . date('Ymd') . (IS_CLI ? '-cli' : '') . '.log';
+
+ return file_put_contents($file, $content, FILE_APPEND) !== false;
+ }
+}
\ No newline at end of file
diff --git a/app/Libs/Pixiv.php b/app/Libs/Pixiv.php
index 987e5e0..b9c12bf 100644
--- a/app/Libs/Pixiv.php
+++ b/app/Libs/Pixiv.php
@@ -1,118 +1,137 @@
- [
- 'Referer: https://www.pixiv.net/ranking.php?mode=daily',
- ],
- ]);
- $json = json_decode($response, true);
- if (!isset($json['contents'])) {
- Tools::log('获取排行榜数据失败!接口返回值:' . $response, Tools::LOG_LEVEL_ERROR);
- return false;
- }
-
- return $json;
- }
-
- /**
- * 获取图片url列表
- * @return array|false
- * @throws \Exception
- */
- public static function getImages()
- {
- $source = Storage::getJson('source');
- if (is_array($source) && self::checkDate($source)) {
- return $source;
- }
-
- // 兼容旧格式
- $source = [
- 'image' => [],
- 'url' => [],
- ];
-
- $picNum = 0;
- for ($page = 1; $page <= 10; $page++) {
-
- $json = self::getRanking($page);
- if($json === false){
- return false;
- }
-
- foreach ($json['contents'] as $item) {
- $source['image'][] = $item['url'];
- $source['url'][] = "artworks/{$item['illust_id']}";
- $picNum++;
-
- if ($picNum >= Config::$limit) {
- break 2;
- }
- }
- }
-
- $source['date'] = date('Y-m-d', strtotime($json['date']));
- Storage::saveJson('source', $source);
-
- return $source;
- }
-
- /**
- * 下载Pixiv缩略图。成功返回临时文件名
- * @param string $url
- * @return string 临时文件名
- */
- public static function downloadImage($url)
- {
- $fileName = pathinfo($url, PATHINFO_BASENAME);
- // 如果 storage 里存了有,就不再重新下载了
- $image = Storage::getImage($fileName);
- if ($image == false) {
- $image = Curl::get($url, [
- CURLOPT_HTTPHEADER => [
- 'Referer: https://www.pixiv.net/ranking.php?mode=daily',
- ],
- ]);
- }
-
- if ($image) {
- $file = explode('/', $url);
- $file = array_pop($file);
- $file = sys_get_temp_dir() . '/' . $file;
- return file_put_contents($file, $image) !== false ? $file : false;
- }
- return false;
- }
-
- /**
- * 检查传入数组的 date 值是否有效(即大于等于昨天)。返回 true 为未过期
- * @param array $data
- * @return bool
- */
- public static function checkDate(array $data)
- {
- if(isset($data['date'])){
- $yesterday = date('Y-m-d', strtotime('-1 day'));
- return $data['date'] >= $yesterday;
- }
-
- return false;
- }
+ [
+ 'Referer: https://www.pixiv.net/ranking.php?mode=daily',
+ ],
+ ]);
+ $json = json_decode($response, true);
+ if (!isset($json['contents'])) {
+ Log::write('获取排行榜数据失败!接口返回值:' . $response, Log::LEVEL_ERROR);
+ return false;
+ }
+
+ return $json;
+ }
+
+ /**
+ * 获取图片url列表
+ * @return array|false
+ * @throws \Exception
+ */
+ public static function getImages()
+ {
+ $source = Storage::getJson('source');
+ if (is_array($source) && self::checkDate($source)) {
+ return $source;
+ }
+
+ $picNum = 0;
+ $sourceJson = [];
+ for ($page = 1; $page <= 10; $page++) {
+
+ $json = self::getRanking($page);
+ if($json === false){
+ return false;
+ }
+
+ foreach ($json['contents'] as $item) {
+ $sourceJson['data'][] = [
+ 'id' => $item['illust_id'],
+ 'url' => $item['url'],
+ 'title' => $item['title'],
+ 'tags' => $item['tags'],
+ 'width' => $item['width'],
+ 'height' => $item['height'],
+ 'page_count' => $item['illust_page_count'],
+ 'rank' => $item['rank'],
+ 'yesterday_rank' => $item['yes_rank'],
+ 'user_id' => $item['user_id'],
+ 'user_name' => $item['user_name'],
+ 'uploaded_at' => $item['illust_upload_timestamp'],
+ ];
+ // image 和 url 是为了兼容 5.x 之前的旧版本
+ $sourceJson['image'][] = $item['url'];
+ $sourceJson['url'][] = "artworks/{$item['illust_id']}";
+ $picNum++;
+
+ if ($picNum >= Config::$limit) {
+ break 2;
+ }
+ }
+ }
+
+ $sourceJson['date'] = date('Y-m-d', strtotime($json['date']));
+ Storage::saveJson('source', $sourceJson);
+
+ return $sourceJson;
+ }
+
+ /**
+ * 下载 Pixiv 缩略图。成功返回临时文件名
+ * @param string $url
+ * @return string 临时文件名
+ */
+ public static function downloadImage($url)
+ {
+ $fileName = pathinfo($url, PATHINFO_BASENAME);
+ // 如果 storage 里存了有,就不再重新下载了
+ $image = Storage::getImage($fileName);
+ if ($image === false) {
+ $image = Curl::get($url, [
+ CURLOPT_HTTPHEADER => [
+ 'Referer: https://www.pixiv.net/ranking.php?mode=daily',
+ ],
+ ]);
+
+ Log::write('下载到数据包大小: ' . strlen($image) . ' 字节');
+ }
+
+ if ($image) {
+ $file = explode('/', $url);
+ $file = array_pop($file);
+ $file = sys_get_temp_dir() . '/' . $file;
+
+ $bytes = file_put_contents($file, $image);
+ Log::write("写入文件 {$file} 大小:{$bytes} 字节");
+
+ return $bytes > 0 ? $file : false;
+ }
+
+ return false;
+ }
+
+ /**
+ * 检查传入数组的 date 值是否有效(即大于等于昨天)。返回 true 为未过期
+ * @param array $data
+ * @return bool
+ */
+ public static function checkDate(array $data)
+ {
+ if(isset($data['date'])){
+ $yesterday = date('Y-m-d', strtotime('-1 day'));
+
+ return $data['date'] >= $yesterday;
+ }
+
+ return false;
+ }
}
\ No newline at end of file
diff --git a/app/Libs/Tools.php b/app/Libs/Request.php
similarity index 52%
rename from app/Libs/Tools.php
rename to app/Libs/Request.php
index 333f37b..45130d9 100644
--- a/app/Libs/Tools.php
+++ b/app/Libs/Request.php
@@ -3,44 +3,38 @@
namespace app\Libs;
/**
- * 工具类
- * Class Tools
- * @package app\Libs
+ * 请求类
*/
-class Tools
+class Request
{
- const LOG_LEVEL_ERROR = 'ERROR';
-
/**
- * 写日志
- * @param string|array $message
- * @param string $level
- * @return bool
+ * 获取当前请求的协议
+ * @return string
*/
- public static function log($message, $level = 'DEBUG')
+ public static function getScheme()
{
- $level = strtoupper($level);
- if (is_array(Config::$log_level) && in_array($level, Config::$log_level)) {
- $file = STORAGE_PATH . 'logs/' . date('Ymd') . (IS_CLI ? '-cli' : '') . '.log';
- $message = is_array($message) ? json_encode($message) : $message;
- $content = "[{$level}] " . date('Y-m-d H:i:s') . " --> {$message}\n";
- if (IS_CLI) {
- echo $content . "\n";
- }
+ if (isset($_SERVER['REQUEST_SCHEME'])) {
+ return $_SERVER['REQUEST_SCHEME'];
+ }
- return file_put_contents($file, $content, FILE_APPEND) !== false;
+ if (
+ (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') ||
+ (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') ||
+ (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
+ ) {
+ return 'https';
}
- return true;
+ return 'http';
}
/**
- * 获取当前 url (不含 query 参数及文件名)
+ * 获取当前 url (以 / 结尾。不含 query 参数及文件名)
* @return string
*/
- public static function getCurrentURL()
+ public static function getCurrentUrl()
{
- $url = self::getRequestScheme() . '://' . $_SERVER['HTTP_HOST'];
+ $url = self::getScheme() . '://' . $_SERVER['HTTP_HOST'];
if (!in_array($_SERVER['SERVER_PORT'], ['80', '443'])) {
$url .= ':' . $_SERVER['SERVER_PORT'];
}
@@ -59,31 +53,15 @@ public static function getCurrentURL()
/**
* 执行刷新线程
*/
- public static function runRefreshThread()
+ public static function execRefreshThread()
{
+ if (Config::$disable_web_job) {
+ return;
+ }
+
+ Config::$proxy = null;
Curl::get(Config::$url . 'index.php?job=refresh', [
CURLOPT_TIMEOUT => 1,
]);
}
-
- /**
- * 获取当前请求的协议
- * @return string
- */
- public static function getRequestScheme()
- {
- if (isset($_SERVER['REQUEST_SCHEME'])) {
- return $_SERVER['REQUEST_SCHEME'];
- }
-
- if (
- (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') ||
- (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') ||
- (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
- ) {
- return 'https';
- }
-
- return 'http';
- }
}
\ No newline at end of file
diff --git a/app/Libs/Storage.php b/app/Libs/Storage.php
index 0cc7099..ae592b2 100644
--- a/app/Libs/Storage.php
+++ b/app/Libs/Storage.php
@@ -34,7 +34,7 @@ public static function get($file)
}
$content = @file_get_contents($file);
if ($content === false) {
- Tools::log("读取 {$file} 文件失败");
+ Log::write("读取 {$file} 文件失败");
return false;
}
@@ -52,7 +52,7 @@ public static function remove($file)
}
/**
- * 清除过期地图片
+ * 清除过期的图片
*/
public static function clearOverdueImages()
{
@@ -70,11 +70,11 @@ public static function clearOverdueImages()
}
}
}
- Tools::log("共计清除过期图片 {$deleteNum} 张");
+ Log::write("共计清除过期图片 {$deleteNum} 张");
}
/**
- * 获取图片内容。文件不存在或无效时返回false
+ * 获取图片内容。文件不存在或无效时返回 false
* @param string $name
* @return mixed|false
*/
diff --git a/app/Libs/Str.php b/app/Libs/Str.php
new file mode 100644
index 0000000..41eb7fc
--- /dev/null
+++ b/app/Libs/Str.php
@@ -0,0 +1,42 @@
+
-
+
@@ -12,48 +12,138 @@
Pixiv 每日排行榜 Top=Config::$limit?> 小挂件
-
+
+
+
-
-
-
- $v): ?>
- = Config::$limit) break; ?>
-