2019-11-13 18:39:22 +00:00
< ? php
/**
* Router
*/
add_action ( 'rest_api_init' , function () {
2019-11-25 15:47:56 +00: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 09:17:54 +00: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 12:35:35 +00:00
register_rest_route ( 'sakura/v1' , '/database/update' , array (
2019-12-15 08:57:53 +00:00
'methods' => 'GET' ,
2019-12-04 12:35:35 +00:00
'callback' => 'update_database' ,
2019-11-28 15:21:24 +00:00
));
2019-12-03 13:20:42 +00:00
register_rest_route ( 'sakura/v1' , '/qqinfo/json' , array (
'methods' => 'GET' ,
'callback' => 'get_qq_info' ,
));
2019-12-04 12:35:35 +00:00
register_rest_route ( 'sakura/v1' , '/qqinfo/avatar' , array (
'methods' => 'GET' ,
'callback' => 'get_qq_avatar' ,
));
2019-11-13 18:39:22 +00:00
});
2019-12-03 13:20:42 +00:00
/**
* QQ info
2019-12-04 12:35:35 +00:00
* https :// sakura . 2 heng . xin / wp - json / sakura / v1 / qqinfo / json
2019-12-03 13:20:42 +00: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 13:48:15 +00:00
'message' => 'Unauthorized client.'
2019-12-03 13:20:42 +00: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 13:42:52 +00:00
'message' => 'success' ,
2019-12-03 13:20:42 +00: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 13:48:15 +00:00
'message' => 'QQ number not exist.'
2019-12-03 13:20:42 +00:00
);
}
} else {
$output = array (
'status' => 400 ,
'success' => false ,
2019-12-03 13:48:15 +00:00
'message' => 'Bad Request'
2019-12-03 13:20:42 +00:00
);
}
$result = new WP_REST_Response ( $output , $output [ 'status' ]);
$result -> set_headers ( array ( 'Content-Type' => 'application/json' ));
return $result ;
}
2019-11-13 18:39:22 +00:00
/**
* Image uploader response
*/
2019-12-03 13:20:42 +00:00
function upload_image ( WP_REST_Request $request )
{
2019-11-25 15:47:56 +00: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 . 2 heng . xin / wp - json / sakura / v1 / image / upload
*/
// $file = $request->get_file_params();
if ( ! check_ajax_referer ( 'wp_rest' , '_wpnonce' , false )) {
2019-12-03 13:20:42 +00:00
$output = array ( 'status' => 403 ,
2019-11-25 15:47:56 +00: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-13 18:39:22 +00:00
2019-11-25 15:47:56 +00: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 13:20:42 +00:00
$result = new WP_REST_Response ( $API_Request , $API_Request [ 'status' ]);
2019-11-14 16:11:02 +00:00
$result -> set_headers ( array ( 'Content-Type' => 'application/json' ));
return $result ;
2019-11-13 18:39:22 +00:00
}
2019-11-14 11:15:53 +00:00
/**
* Chevereto upload interface
*/
2019-12-03 13:20:42 +00:00
function Chevereto_API ( $image )
{
$upload_url = akina_option ( 'cheverto_url' ) . '/api/1/upload' ;
2019-11-25 15:47:56 +00:00
$args = array (
'body' => array (
'source' => base64_encode ( $image ),
2019-12-03 13:20:42 +00:00
'key' => akina_option ( 'chevereto_api_key' ),
),
2019-11-14 11:15:53 +00:00
);
2019-11-25 15:47:56 +00:00
$response = wp_remote_post ( $upload_url , $args );
$reply = json_decode ( $response [ " body " ]);
2019-11-14 11:15:53 +00: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-13 18:39:22 +00:00
/**
* Imgur upload interface
*/
2019-12-03 13:20:42 +00:00
function Imgur_API ( $image )
{
2019-11-13 18:39:22 +00:00
$client_id = akina_option ( 'imgur_client_id' );
2019-11-25 15:47:56 +00:00
$upload_url = akina_option ( 'imgur_upload_image_proxy' );
$args = array (
'headers' => array (
2019-12-03 13:20:42 +00:00
'Authorization' => 'Client-ID ' . $client_id ,
2019-11-25 15:47:56 +00:00
),
'body' => array (
2019-12-03 13:20:42 +00:00
'image' => base64_encode ( $image ),
),
2019-11-25 15:47:56 +00:00
);
2019-11-13 18:39:22 +00:00
2019-11-25 15:47:56 +00:00
$response = wp_remote_post ( $upload_url , $args );
$reply = json_decode ( $response [ " body " ]);
2019-11-13 18:39:22 +00:00
if ( $reply -> success && $reply -> status == 200 ) {
$status = 200 ;
2019-11-14 11:15:53 +00:00
$success = true ;
2019-11-13 18:39:22 +00:00
$message = " success " ;
$link = $reply -> data -> link ;
$proxy = akina_option ( 'cmt_image_proxy' ) . $link ;
} else {
$status = $reply -> status ;
2019-11-14 11:15:53 +00:00
$success = false ;
2019-11-13 18:39:22 +00: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 11:15:53 +00:00
'success' => $success ,
2019-11-13 18:39:22 +00:00
'message' => $message ,
'link' => $link ,
'proxy' => $proxy ,
);
return $output ;
}
2019-11-14 11:15:53 +00:00
/**
* smms upload interface
*/
2019-12-03 13:20:42 +00:00
function SMMS_API ( $image )
{
2019-11-25 15:47:56 +00: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 );
$args = array (
2019-12-13 07:34:14 +00:00
" headers " => " Content-Type: multipart/form-data; boundary= $Boundary\r\n\r\nAuthorization : Basic $client_id\r\n\r\nUser -Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 " ,
" body " => " -- $Boundary\r\nContent -Disposition: form-data; name= \" smfile \" ; filename= \" $filename\ " \r\n\r\n $bits\r\n\r\n -- $Boundary -- "
2019-11-25 15:47:56 +00:00
);
2019-11-14 11:15:53 +00:00
2019-11-25 15:47:56 +00:00
$response = wp_remote_post ( $upload_url , $args );
$reply = json_decode ( $response [ " body " ]);
2019-11-13 18:39:22 +00:00
2019-11-25 15:47:56 +00: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 05:53:37 +00:00
$status = 200 ; // sm.ms 接口不规范,建议检测到重复的情况下返回标准化的 code, 并单独把 url 放进一个字段
2019-11-25 15:47:56 +00: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-13 18:39:22 +00:00
}
/*
* 定制实时搜索 rest api
2019-11-15 01:23:07 +00:00
* @ rest api接口路径: https :// sakura . 2 heng . xin / wp - json / sakura / v1 / cache_search / json
2019-11-13 18:39:22 +00:00
* @ 可在cache_search_json () 函数末尾通过设置 HTTP header 控制 json 缓存时间
*/
2019-12-03 13:20:42 +00:00
function cache_search_json ()
{
2019-11-13 18:39:22 +00: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-24 12:03:43 +00:00
$output .= '{"type":"post","link":"' . get_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-13 18:39:22 +00: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 05:53:37 +00:00
$result -> set_headers (
array (
'Content-Type' => 'application/json' ,
2019-12-03 13:20:42 +00:00
'Cache-Control' => 'max-age=3600' , // json 缓存控制
2019-11-26 05:53:37 +00:00
)
);
2019-11-13 18:39:22 +00:00
return $result ;
2019-11-14 16:14:07 +00:00
}
2019-11-27 09:17:54 +00:00
/*
* 随机封面图 rest api
* @ rest api接口路径: https :// sakura . 2 heng . xin / wp - json / sakura / v1 / image / cover
*/
function cover_gallery () {
2019-12-04 12:35:35 +00:00
global $wpdb , $sakura_image_array ;
$img_array = json_decode ( $sakura_image_array , true );
2019-11-28 15:21:24 +00:00
$img = array_rand ( $img_array );
2019-12-04 07:17:05 +00:00
$img_domain = akina_option ( 'cover_cdn' ) ? akina_option ( 'cover_cdn' ) : get_template_directory_uri ();
2019-12-03 14:35:15 +00: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 15:21:24 +00:00
$data = array ( 'cover image' );
2019-11-27 15:32:41 +00:00
$response = new WP_REST_Response ( $data );
2019-11-28 15:21:24 +00:00
$response -> set_status ( 302 );
$response -> header ( 'Location' , $imgurl );
2019-11-27 15:32:41 +00:00
return $response ;
2019-11-27 09:17:54 +00:00
}
/*
* 随机文章特色图 rest api
* @ rest api接口路径: https :// sakura . 2 heng . xin / wp - json / sakura / v1 / image / feature
*/
function feature_gallery () {
2019-12-04 12:35:35 +00:00
global $wpdb , $sakura_image_array ;
$img_array = json_decode ( $sakura_image_array , true );
2019-11-28 15:21:24 +00:00
$img = array_rand ( $img_array );
2019-12-04 07:17:05 +00:00
$img_domain = akina_option ( 'cover_cdn' ) ? akina_option ( 'cover_cdn' ) : get_template_directory_uri ();
2019-12-03 14:35:15 +00:00
if ( strpos ( $_SERVER [ 'HTTP_ACCEPT' ], 'image/webp' )) {
2019-12-21 12:25:28 +00:00
$imgurl = $img_domain . " /manifest/ " . $img_array [ $img ][ " webp " ][ 0 ];
2019-12-03 14:35:15 +00:00
} else {
2019-12-21 12:25:28 +00:00
$imgurl = $img_domain . " /manifest/ " . $img_array [ $img ][ " jpeg " ][ 0 ];
2019-12-03 14:35:15 +00:00
}
2019-11-28 15:21:24 +00:00
$data = array ( 'cover image' );
2019-11-27 15:32:41 +00:00
$response = new WP_REST_Response ( $data );
2019-11-28 15:21:24 +00:00
$response -> set_status ( 302 );
$response -> header ( 'Location' , $imgurl );
2019-11-27 15:32:41 +00:00
return $response ;
2019-11-28 15:21:24 +00:00
}
/*
2019-12-04 12:35:35 +00:00
* update database rest api
* @ rest api接口路径: https :// sakura . 2 heng . xin / wp - json / sakura / v1 / database / update
2019-11-28 15:21:24 +00:00
*/
2019-12-04 12:35:35 +00:00
function update_database () {
2019-12-15 08:57:53 +00:00
global $wpdb ;
$sakura_table_name = $wpdb -> base_prefix . 'sakura' ;
$img_domain = akina_option ( 'cover_cdn' ) ? akina_option ( 'cover_cdn' ) : get_template_directory_uri ();
$manifest = file_get_contents ( $img_domain . " /manifest/manifest.json " );
if ( $manifest ) {
$manifest = array (
2019-12-24 12:03:43 +00:00
" mate_key " => " manifest_json " ,
" mate_value " => $manifest
2019-11-28 15:21:24 +00:00
);
2019-12-15 08:57:53 +00:00
$time = array (
2019-12-24 12:03:43 +00:00
" mate_key " => " json_time " ,
" mate_value " => date ( " Y-m-d H:i:s " , time ())
2019-12-15 08:57:53 +00:00
);
$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 );
$output = " manifest.json has been stored into database. " ;
} else {
$output = " manifest.json not found, please ensure your url is corrent. " ;
2019-11-28 15:21:24 +00:00
}
2019-12-15 08:57:53 +00:00
$result = new WP_REST_Response ( $output , 200 );
return $result ;
2019-12-03 13:42:52 +00:00
}
2019-12-04 12:35:35 +00:00
/**
* QQ头像链接解密
2019-12-05 10:12:31 +00:00
* https :// sakura . 2 heng . xin / wp - json / sakura / v1 / qqinfo / avatar
2019-12-04 12:35:35 +00:00
*/
function get_qq_avatar (){
global $sakura_privkey ;
2019-12-05 15:07:28 +00:00
$encrypted = $_GET [ " qq " ];
if ( isset ( $encrypted )){
2019-12-26 11:52:06 +00:00
$iv = str_repeat ( $sakura_privkey , 2 );
2019-12-05 15:07:28 +00:00
$encrypted = urldecode ( base64_decode ( $encrypted ));
2019-12-21 13:18:32 +00:00
$qq_number = openssl_decrypt ( $encrypted , 'aes-128-cbc' , $sakura_privkey , 0 , $iv );
2019-12-05 15:07:28 +00:00
preg_match ( '/^\d{3,}$/' , $qq_number , $matches );
$imgurl = 'https://q2.qlogo.cn/headimg_dl?dst_uin=' . $matches [ 0 ] . '&spec=100' ;
2019-12-05 15:31:33 +00:00
if ( akina_option ( 'qq_avatar_link' ) == 'type_2' ){
2019-12-05 15:07:28 +00:00
$imgdata = file_get_contents ( $imgurl );
header ( " Content-type: image/jpeg " );
2019-12-05 15:31:33 +00:00
header ( " Cache-Control: max-age=86400 " );
2019-12-05 15:07:28 +00:00
echo $imgdata ;
} else {
$response = new WP_REST_Response ();
2019-12-05 15:31:33 +00:00
$response -> set_status ( 301 );
2019-12-05 15:07:28 +00:00
$response -> header ( 'Location' , $imgurl );
return $response ;
}
}
2019-12-04 12:35:35 +00:00
}