sakura/inc/api.php

455 lines
16 KiB
PHP
Raw Normal View History

2019-11-14 02:39:22 +08:00
<?php
/**
* Router
*/
add_action('rest_api_init', function () {
2019-11-25 23:47:56 +08:00
register_rest_route('sakura/v1', '/image/upload', array(
'methods' => 'POST',
'callback' => 'upload_image',
));
register_rest_route('sakura/v1', '/cache_search/json', array(
'methods' => 'GET',
'callback' => 'cache_search_json',
));
2019-11-27 17:17:54 +08:00
register_rest_route('sakura/v1', '/image/cover', array(
'methods' => 'GET',
'callback' => 'cover_gallery',
));
register_rest_route('sakura/v1', '/image/feature', array(
'methods' => 'GET',
'callback' => 'feature_gallery',
));
2019-12-04 20:35:35 +08:00
register_rest_route('sakura/v1', '/database/update', array(
2019-11-28 23:21:24 +08:00
'methods' => 'POST',
2019-12-04 20:35:35 +08:00
'callback' => 'update_database',
2019-11-28 23:21:24 +08:00
));
2019-12-03 21:20:42 +08:00
register_rest_route('sakura/v1', '/qqinfo/json', array(
'methods' => 'GET',
'callback' => 'get_qq_info',
));
2019-12-04 20:35:35 +08:00
register_rest_route('sakura/v1', '/qqinfo/avatar', array(
'methods' => 'GET',
'callback' => 'get_qq_avatar',
));
2019-11-14 02:39:22 +08:00
});
2019-12-03 21:20:42 +08:00
/**
* QQ info
2019-12-04 20:35:35 +08:00
* https://sakura.2heng.xin/wp-json/sakura/v1/qqinfo/json
2019-12-03 21:20:42 +08:00
*/
function get_qq_info(WP_REST_Request $request)
{
if (!check_ajax_referer('wp_rest', '_wpnonce', false)) {
$output = array(
'status' => 403,
'success' => false,
2019-12-03 21:48:15 +08:00
'message' => 'Unauthorized client.'
2019-12-03 21:20:42 +08:00
);
} elseif ($_GET['qq']) {
$qq = $_GET['qq'];
/**
* TODO: 设置host国外服务器默认解析的不是国内IP可能无法获取数据
* 182.254.92.32 r.qzone.qq.com
* 参考https://www.php.net/manual/zh/function.file-get-contents.php#108309
*/
$get_info = file_get_contents('http://r.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?get_nick=1&uins=' . $qq);
$get_info = mb_convert_encoding($get_info, "UTF-8", "GBK");
$name = json_decode(substr($get_info, 17, -1), true);
if ($name) {
$output = array(
'status' => 200,
'success' => true,
2019-12-03 21:42:52 +08:00
'message' => 'success',
2019-12-03 21:20:42 +08:00
'avatar' => 'https://q.qlogo.cn/headimg_dl?dst_uin=' . $qq . '&spec=100',
'name' => $name[$qq][6],
);
} else {
$output = array(
'status' => 404,
'success' => false,
2019-12-03 21:48:15 +08:00
'message' => 'QQ number not exist.'
2019-12-03 21:20:42 +08:00
);
}
} else {
$output = array(
'status' => 400,
'success' => false,
2019-12-03 21:48:15 +08:00
'message' => 'Bad Request'
2019-12-03 21:20:42 +08:00
);
}
$result = new WP_REST_Response($output, $output['status']);
$result->set_headers(array('Content-Type' => 'application/json'));
return $result;
}
2019-11-14 02:39:22 +08:00
/**
* Image uploader response
*/
2019-12-03 21:20:42 +08:00
function upload_image(WP_REST_Request $request)
{
2019-11-25 23:47:56 +08:00
// see: https://developer.wordpress.org/rest-api/requests/
// handle file params $file === $_FILES
/**
* curl \
* -F "filecomment=This is an img file" \
* -F "cmt_img_file=@screenshot.jpg" \
* https://dev.2heng.xin/wp-json/sakura/v1/image/upload
*/
// $file = $request->get_file_params();
if (!check_ajax_referer('wp_rest', '_wpnonce', false)) {
2019-12-03 21:20:42 +08:00
$output = array('status' => 403,
2019-11-25 23:47:56 +08:00
'success' => false,
'message' => 'Unauthorized client.',
'link' => "https://view.moezx.cc/images/2019/11/14/step04.md.png",
'proxy' => akina_option('cmt_image_proxy') . "https://view.moezx.cc/images/2019/11/14/step04.md.png",
);
$result = new WP_REST_Response($output, 403);
$result->set_headers(array('Content-Type' => 'application/json'));
return $result;
}
2019-11-14 02:39:22 +08:00
2019-11-25 23:47:56 +08:00
switch (akina_option("img_upload_api")) {
case 'imgur':
$image = file_get_contents($_FILES["cmt_img_file"]["tmp_name"]);
$API_Request = Imgur_API($image);
break;
case 'smms':
$image = $_FILES;
$API_Request = SMMS_API($image);
break;
case 'chevereto':
$image = file_get_contents($_FILES["cmt_img_file"]["tmp_name"]);
$API_Request = Chevereto_API($image);
break;
}
2019-12-03 21:20:42 +08:00
$result = new WP_REST_Response($API_Request, $API_Request['status']);
2019-11-15 00:11:02 +08:00
$result->set_headers(array('Content-Type' => 'application/json'));
return $result;
2019-11-14 02:39:22 +08:00
}
2019-11-14 19:15:53 +08:00
/**
* Chevereto upload interface
*/
2019-12-03 21:20:42 +08:00
function Chevereto_API($image)
{
$upload_url = akina_option('cheverto_url') . '/api/1/upload';
2019-11-25 23:47:56 +08:00
$args = array(
'body' => array(
'source' => base64_encode($image),
2019-12-03 21:20:42 +08:00
'key' => akina_option('chevereto_api_key'),
),
2019-11-14 19:15:53 +08:00
);
2019-11-25 23:47:56 +08:00
$response = wp_remote_post($upload_url, $args);
$reply = json_decode($response["body"]);
2019-11-14 19:15:53 +08:00
if ($reply->status_txt == 'OK' && $reply->status_code == 200) {
$status = 200;
$success = true;
$message = "success";
$link = $reply->image->image->url;
$proxy = akina_option('cmt_image_proxy') . $link;
} else {
$status = $reply->status_code;
$success = false;
$message = $reply->error->message;
$link = 'https://view.moezx.cc/images/2019/10/28/default_d_h_large.gif';
$proxy = akina_option('cmt_image_proxy') . $link;
}
$output = array(
'status' => $status,
'success' => $success,
'message' => $message,
'link' => $link,
'proxy' => $proxy,
);
return $output;
}
2019-11-14 02:39:22 +08:00
/**
* Imgur upload interface
*/
2019-12-03 21:20:42 +08:00
function Imgur_API($image)
{
2019-11-14 02:39:22 +08:00
$client_id = akina_option('imgur_client_id');
2019-11-25 23:47:56 +08:00
$upload_url = akina_option('imgur_upload_image_proxy');
$args = array(
'headers' => array(
2019-12-03 21:20:42 +08:00
'Authorization' => 'Client-ID ' . $client_id,
2019-11-25 23:47:56 +08:00
),
'body' => array(
2019-12-03 21:20:42 +08:00
'image' => base64_encode($image),
),
2019-11-25 23:47:56 +08:00
);
2019-11-14 02:39:22 +08:00
2019-11-25 23:47:56 +08:00
$response = wp_remote_post($upload_url, $args);
$reply = json_decode($response["body"]);
2019-11-14 02:39:22 +08:00
if ($reply->success && $reply->status == 200) {
$status = 200;
2019-11-14 19:15:53 +08:00
$success = true;
2019-11-14 02:39:22 +08:00
$message = "success";
$link = $reply->data->link;
$proxy = akina_option('cmt_image_proxy') . $link;
} else {
$status = $reply->status;
2019-11-14 19:15:53 +08:00
$success = false;
2019-11-14 02:39:22 +08:00
$message = $reply->data->error;
$link = 'https://view.moezx.cc/images/2019/10/28/default_d_h_large.gif';
$proxy = akina_option('cmt_image_proxy') . $link;
}
$output = array(
'status' => $status,
2019-11-14 19:15:53 +08:00
'success' => $success,
2019-11-14 02:39:22 +08:00
'message' => $message,
'link' => $link,
'proxy' => $proxy,
);
return $output;
}
2019-11-14 19:15:53 +08:00
/**
* smms upload interface
*/
2019-12-03 21:20:42 +08:00
function SMMS_API($image)
{
2019-11-25 23:47:56 +08:00
$client_id = akina_option('smms_client_id');
$upload_url = "https://sm.ms/api/v2/upload";
$filename = $image['cmt_img_file']['name'];
$filedata = $image['cmt_img_file']['tmp_name'];
$Boundary = wp_generate_password();
$bits = file_get_contents($filedata);
$headers = array();
array_push($headers, "Content-Type: multipart/form-data; boundary=$Boundary");
2019-11-26 13:53:37 +08:00
array_push($headers, '');
2019-11-25 23:47:56 +08:00
array_push($headers, "Authorization: Basic " . $client_id);
2019-11-26 13:53:37 +08:00
array_push($headers, '');
2019-11-25 23:47:56 +08:00
array_push($headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97");
2019-11-26 13:53:37 +08:00
$headers = implode("\r\n", $headers);
2019-11-25 23:47:56 +08:00
$fields = array();
array_push($fields, "--" . $Boundary);
array_push($fields, "Content-Disposition: form-data; name=\"smfile\"; filename=\"$filename\"");
array_push($fields, '');
array_push($fields, $bits);
array_push($fields, '');
array_push($fields, "--" . $Boundary . "--");
$fields = implode("\r\n", $fields);
$args = array(
'headers' => $headers,
2019-12-03 21:20:42 +08:00
'body' => $fields,
2019-11-25 23:47:56 +08:00
);
2019-11-14 19:15:53 +08:00
2019-11-25 23:47:56 +08:00
$response = wp_remote_post($upload_url, $args);
$reply = json_decode($response["body"]);
2019-11-14 02:39:22 +08:00
2019-11-25 23:47:56 +08:00
if ($reply->success && $reply->code == 'success') {
$status = 200;
$success = true;
$message = $reply->message;
$link = $reply->data->url;
$proxy = akina_option('cmt_image_proxy') . $link;
} else if (preg_match("/Image upload repeated limit/i", $reply->message, $matches)) {
2019-11-26 13:53:37 +08:00
$status = 200; // sm.ms 接口不规范,建议检测到重复的情况下返回标准化的 code并单独把 url 放进一个字段
2019-11-25 23:47:56 +08:00
$success = true;
$message = $reply->message;
$link = str_replace('Image upload repeated limit, this image exists at: ', '', $reply->message);
$proxy = akina_option('cmt_image_proxy') . $link;
} else {
$status = 400;
$success = false;
$message = $reply->message;
$link = 'https://view.moezx.cc/images/2019/10/28/default_d_h_large.gif';
$proxy = akina_option('cmt_image_proxy') . $link;
}
$output = array(
'status' => $status,
'success' => $success,
'message' => $message,
'link' => $link,
'proxy' => $proxy,
);
return $output;
2019-11-14 02:39:22 +08:00
}
/*
* 定制实时搜索 rest api
2019-11-15 09:23:07 +08:00
* @rest api接口路径https://sakura.2heng.xin/wp-json/sakura/v1/cache_search/json
2019-11-14 02:39:22 +08:00
* @可在cache_search_json()函数末尾通过设置 HTTP header 控制 json 缓存时间
*/
2019-12-03 21:20:42 +08:00
function cache_search_json()
{
2019-11-14 02:39:22 +08:00
$vowels = array("[", "{", "]", "}", "<", ">", "\r\n", "\r", "\n", "-", "'", '"', '`', " ", ":", ";", '\\', " ", "toc");
$regex = <<<EOS
/<\/?[a-zA-Z]+("[^"]*"|'[^']*'|[^'">])*>|begin[\S\s]*\/begin|hermit[\S\s]*\/hermit|img[\S\s]*\/img|{{.*?}}|:.*?:/m
EOS;
$posts = new WP_Query('posts_per_page=-1&post_status=publish&post_type=post');
while ($posts->have_posts()): $posts->the_post();
2019-12-03 21:20:42 +08:00
$output .= '{"type":"post","link":"' . get_post_permalink() . '","title":' . json_encode(get_the_title()) . ',"comments":"' . get_comments_number('0', '1', '%') . '","text":' . json_encode(str_replace($vowels, " ", preg_replace($regex, ' ', get_the_content()))) . '},';
2019-11-14 02:39:22 +08:00
endwhile;
wp_reset_postdata();
$pages = get_pages();
foreach ($pages as $page) {
$output .= '{"type":"page","link":"' . get_page_link($page) . '","title":' . json_encode($page->post_title) . ',"comments":"' . $page->comment_count . '","text":' . json_encode(str_replace($vowels, " ", preg_replace($regex, ' ', $page->post_content))) . '},';
}
$tags = get_tags();
foreach ($tags as $tag) {
$output .= '{"type":"tag","link":"' . get_term_link($tag) . '","title":' . json_encode($tag->name) . ',"comments":"","text":""},';
}
$categories = get_categories();
foreach ($categories as $category) {
$output .= '{"type":"category","link":"' . get_term_link($category) . '","title":' . json_encode($category->name) . ',"comments":"","text":""},';
}
if (akina_option('live_search_comment')) {
$comments = get_comments();
foreach ($comments as $comment) {
$is_private = get_comment_meta($comment->comment_ID, '_private', true);
if ($is_private) {
$output .= '{"type":"comment","link":"' . get_comment_link($comment) . '","title":' . json_encode(get_the_title($comment->comment_post_ID)) . ',"comments":"","text":' . json_encode($comment->comment_author . "" . __("The comment is private", "sakura") /*该评论为私密评论*/) . '},';
continue;
} else {
$output .= '{"type":"comment","link":"' . get_comment_link($comment) . '","title":' . json_encode(get_the_title($comment->comment_post_ID)) . ',"comments":"","text":' . json_encode(str_replace($vowels, " ", preg_replace($regex, " ", $comment->comment_author . "" . $comment->comment_content))) . '},';
}
}
}
$output = substr($output, 0, strlen($output) - 1);
$data = '[' . $output . ']';
$result = new WP_REST_Response(json_decode($data), 200);
2019-11-26 13:53:37 +08:00
$result->set_headers(
array(
'Content-Type' => 'application/json',
2019-12-03 21:20:42 +08:00
'Cache-Control' => 'max-age=3600', // json 缓存控制
2019-11-26 13:53:37 +08:00
)
);
2019-11-14 02:39:22 +08:00
return $result;
2019-11-15 00:14:07 +08:00
}
2019-11-27 17:17:54 +08:00
/*
* 随机封面图 rest api
* @rest api接口路径https://sakura.2heng.xin/wp-json/sakura/v1/image/cover
*/
function cover_gallery() {
2019-12-04 20:35:35 +08:00
global $wpdb,$sakura_image_array;
$img_array = json_decode($sakura_image_array, true);
2019-11-28 23:21:24 +08:00
$img = array_rand($img_array);
2019-12-04 15:17:05 +08:00
$img_domain = akina_option('cover_cdn') ? akina_option('cover_cdn') : get_template_directory_uri();
2019-12-03 22:35:15 +08:00
if(strpos($_SERVER['HTTP_ACCEPT'], 'image/webp')) {
$imgurl = $img_domain . "/manifest/" . $img_array[$img]["webp"][0];
} else {
$imgurl = $img_domain . "/manifest/" . $img_array[$img]["jpeg"][0];
}
2019-11-28 23:21:24 +08:00
$data = array('cover image');
2019-11-27 23:32:41 +08:00
$response = new WP_REST_Response($data);
2019-11-28 23:21:24 +08:00
$response->set_status(302);
$response->header('Location', $imgurl);
2019-11-27 23:32:41 +08:00
return $response;
2019-11-27 17:17:54 +08:00
}
/*
* 随机文章特色图 rest api
* @rest api接口路径https://sakura.2heng.xin/wp-json/sakura/v1/image/feature
*/
function feature_gallery() {
2019-12-04 20:35:35 +08:00
global $wpdb,$sakura_image_array;
$img_array = json_decode($sakura_image_array, true);
2019-11-28 23:21:24 +08:00
$img = array_rand($img_array);
2019-12-04 15:17:05 +08:00
$img_domain = akina_option('cover_cdn') ? akina_option('cover_cdn') : get_template_directory_uri();
2019-12-03 22:35:15 +08:00
if(strpos($_SERVER['HTTP_ACCEPT'], 'image/webp')) {
$imgurl = $img_domain . "/manifest/" . $img_array[$img]["webp"][1];
} else {
$imgurl = $img_domain . "/manifest/" . $img_array[$img]["jpeg"][1];
}
2019-11-28 23:21:24 +08:00
$data = array('cover image');
2019-11-27 23:32:41 +08:00
$response = new WP_REST_Response($data);
2019-11-28 23:21:24 +08:00
$response->set_status(302);
$response->header('Location', $imgurl);
2019-11-27 23:32:41 +08:00
return $response;
2019-11-28 23:21:24 +08:00
}
/*
2019-12-04 20:35:35 +08:00
* update database rest api
* @rest api接口路径https://sakura.2heng.xin/wp-json/sakura/v1/database/update
2019-11-28 23:21:24 +08:00
*/
2019-12-04 20:35:35 +08:00
function update_database() {
2019-12-01 17:44:29 +08:00
$username = $_SERVER['PHP_AUTH_USER'];
$password = $_SERVER['PHP_AUTH_PW'];
$user = wp_authenticate($username, $password);
if (is_a($user, 'WP_User')) {
if (in_array('administrator', (array) $user->roles)) {
global $wpdb;
$sakura_table_name = $wpdb->base_prefix.'sakura';
2019-12-04 20:35:35 +08:00
if(isset($_FILES["manifest"])) {
$manifest = array(
"key" => "manifest_json",
"value" => file_get_contents($_FILES["manifest"]["tmp_name"])
);
$time = array(
"key" => "json_time",
"value" => date("Y-m-d H:i:s",time())
);
$wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='manifest_json'");
$wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='json_time'");
$wpdb->insert($sakura_table_name,$manifest);
$wpdb->insert($sakura_table_name,$time);
$message = "manifest.json has been stored into database.";
}
2019-12-01 17:44:29 +08:00
$output = array(
'status' => 200,
'success' => true,
2019-12-04 20:35:35 +08:00
'message' => $message
2019-12-01 17:44:29 +08:00
);
$result = new WP_REST_Response($output, 200);
$result->set_headers(array('Content-Type' => 'application/json'));
return $result;
}
2019-11-28 23:21:24 +08:00
} else {
$output = array(
'status' => 401,
'success' => false,
'message' => 'Not Authorized.'
);
$result = new WP_REST_Response($output, 401);
$result->set_headers(array('Content-Type' => 'application/json'));
return $result;
}
2019-12-03 21:42:52 +08:00
}
2019-12-04 20:35:35 +08:00
/**
* QQ头像链接解密
2019-12-05 18:12:31 +08:00
* https://sakura.2heng.xin/wp-json/sakura/v1/qqinfo/avatar
2019-12-04 20:35:35 +08:00
*/
function get_qq_avatar(){
global $sakura_privkey;
2019-12-05 23:07:28 +08:00
$encrypted=$_GET["qq"];
if(isset($encrypted)){
$encrypted = urldecode(base64_decode($encrypted));
$qq_number = openssl_decrypt($encrypted, 'aes-128-cbc', $sakura_privkey, 0);
preg_match('/^\d{3,}$/', $qq_number, $matches);
$imgurl='https://q2.qlogo.cn/headimg_dl?dst_uin='.$matches[0].'&spec=100';
if(akina_option('qq_avatar_link')=='type_1'){
$imgdata = file_get_contents($imgurl);
header("Content-type: image/jpeg");
echo $imgdata;
}else{
$response = new WP_REST_Response();
$response->set_status(302);
$response->header('Location', $imgurl);
return $response;
}
}
2019-12-04 20:35:35 +08:00
}