Merge branch 'dev' into pr-branch
							
								
								
									
										98
									
								
								inc/api.php
								
								
								
								
							
							
						
						| 
						 | 
					@ -20,16 +20,75 @@ add_action('rest_api_init', function () {
 | 
				
			||||||
        'methods' => 'GET',
 | 
					        'methods' => 'GET',
 | 
				
			||||||
        'callback' => 'feature_gallery',
 | 
					        'callback' => 'feature_gallery',
 | 
				
			||||||
    ));
 | 
					    ));
 | 
				
			||||||
    register_rest_route('sakura/v1', '/image/json', array(
 | 
					    register_rest_route('sakura/v1', '/image/manifest', array(
 | 
				
			||||||
        'methods' => 'POST',
 | 
					        'methods' => 'POST',
 | 
				
			||||||
        'callback' => 'update_manifest_json',
 | 
					        'callback' => 'update_manifest_json',
 | 
				
			||||||
    ));
 | 
					    ));
 | 
				
			||||||
 | 
					    register_rest_route('sakura/v1', '/qqinfo/json', array(
 | 
				
			||||||
 | 
					        'methods' => 'GET',
 | 
				
			||||||
 | 
					        'callback' => 'get_qq_info',
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * QQ info
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function get_qq_info(WP_REST_Request $request)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!check_ajax_referer('wp_rest', '_wpnonce', false)) {
 | 
				
			||||||
 | 
					        $output = array(
 | 
				
			||||||
 | 
					            'status' => 403,
 | 
				
			||||||
 | 
					            'success' => false,
 | 
				
			||||||
 | 
					            'message' => 'Unauthorized client.',
 | 
				
			||||||
 | 
					            'avatar' => 'https://q2.qlogo.cn/headimg_dl?dst_uin=0&spec=100',
 | 
				
			||||||
 | 
					            'name' => '',
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    } 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,
 | 
				
			||||||
 | 
					                'avatar' => 'https://q.qlogo.cn/headimg_dl?dst_uin=' . $qq . '&spec=100',
 | 
				
			||||||
 | 
					                'name' => $name[$qq][6],
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $output = array(
 | 
				
			||||||
 | 
					                'status' => 404,
 | 
				
			||||||
 | 
					                'success' => false,
 | 
				
			||||||
 | 
					                'message' => 'QQ number not exist.',
 | 
				
			||||||
 | 
					                'avatar' => 'https://q.qlogo.cn/headimg_dl?dst_uin=0&spec=100',
 | 
				
			||||||
 | 
					                'name' => '',
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        $output = array(
 | 
				
			||||||
 | 
					            'status' => 400,
 | 
				
			||||||
 | 
					            'success' => false,
 | 
				
			||||||
 | 
					            'message' => 'Bad Request',
 | 
				
			||||||
 | 
					            'avatar' => 'https://q2.qlogo.cn/headimg_dl?dst_uin=0&spec=100',
 | 
				
			||||||
 | 
					            'name' => '',
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $result = new WP_REST_Response($output, $output['status']);
 | 
				
			||||||
 | 
					    $result->set_headers(array('Content-Type' => 'application/json'));
 | 
				
			||||||
 | 
					    return $result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Image uploader response
 | 
					 * Image uploader response
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function upload_image(WP_REST_Request $request) {
 | 
					function upload_image(WP_REST_Request $request)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    // see: https://developer.wordpress.org/rest-api/requests/
 | 
					    // see: https://developer.wordpress.org/rest-api/requests/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // handle file params $file === $_FILES
 | 
					    // handle file params $file === $_FILES
 | 
				
			||||||
| 
						 | 
					@ -41,8 +100,7 @@ function upload_image(WP_REST_Request $request) {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    // $file = $request->get_file_params();
 | 
					    // $file = $request->get_file_params();
 | 
				
			||||||
    if (!check_ajax_referer('wp_rest', '_wpnonce', false)) {
 | 
					    if (!check_ajax_referer('wp_rest', '_wpnonce', false)) {
 | 
				
			||||||
        $output = array(
 | 
					        $output = array('status' => 403,
 | 
				
			||||||
            'status' => 403,
 | 
					 | 
				
			||||||
            'success' => false,
 | 
					            'success' => false,
 | 
				
			||||||
            'message' => 'Unauthorized client.',
 | 
					            'message' => 'Unauthorized client.',
 | 
				
			||||||
            'link' => "https://view.moezx.cc/images/2019/11/14/step04.md.png",
 | 
					            'link' => "https://view.moezx.cc/images/2019/11/14/step04.md.png",
 | 
				
			||||||
| 
						 | 
					@ -68,7 +126,7 @@ function upload_image(WP_REST_Request $request) {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $result = new WP_REST_Response($API_Request, $API_Request->status);
 | 
					    $result = new WP_REST_Response($API_Request, $API_Request['status']);
 | 
				
			||||||
    $result->set_headers(array('Content-Type' => 'application/json'));
 | 
					    $result->set_headers(array('Content-Type' => 'application/json'));
 | 
				
			||||||
    return $result;
 | 
					    return $result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -76,13 +134,14 @@ function upload_image(WP_REST_Request $request) {
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Chevereto upload interface
 | 
					 * Chevereto upload interface
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function Chevereto_API($image) {
 | 
					function Chevereto_API($image)
 | 
				
			||||||
    $upload_url = akina_option('cheverto_url').'/api/1/upload';
 | 
					{
 | 
				
			||||||
 | 
					    $upload_url = akina_option('cheverto_url') . '/api/1/upload';
 | 
				
			||||||
    $args = array(
 | 
					    $args = array(
 | 
				
			||||||
        'body' => array(
 | 
					        'body' => array(
 | 
				
			||||||
            'source' => base64_encode($image),
 | 
					            'source' => base64_encode($image),
 | 
				
			||||||
            'key' => akina_option('chevereto_api_key')
 | 
					            'key' => akina_option('chevereto_api_key'),
 | 
				
			||||||
        )
 | 
					        ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $response = wp_remote_post($upload_url, $args);
 | 
					    $response = wp_remote_post($upload_url, $args);
 | 
				
			||||||
| 
						 | 
					@ -114,16 +173,17 @@ function Chevereto_API($image) {
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Imgur upload interface
 | 
					 * Imgur upload interface
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function Imgur_API($image) {
 | 
					function Imgur_API($image)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    $client_id = akina_option('imgur_client_id');
 | 
					    $client_id = akina_option('imgur_client_id');
 | 
				
			||||||
    $upload_url = akina_option('imgur_upload_image_proxy');
 | 
					    $upload_url = akina_option('imgur_upload_image_proxy');
 | 
				
			||||||
    $args = array(
 | 
					    $args = array(
 | 
				
			||||||
        'headers' => array(
 | 
					        'headers' => array(
 | 
				
			||||||
            'Authorization' => 'Client-ID ' . $client_id
 | 
					            'Authorization' => 'Client-ID ' . $client_id,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        'body' => array(
 | 
					        'body' => array(
 | 
				
			||||||
            'image' => base64_encode($image)
 | 
					            'image' => base64_encode($image),
 | 
				
			||||||
        )
 | 
					        ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $response = wp_remote_post($upload_url, $args);
 | 
					    $response = wp_remote_post($upload_url, $args);
 | 
				
			||||||
| 
						 | 
					@ -155,7 +215,8 @@ function Imgur_API($image) {
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * smms upload interface
 | 
					 * smms upload interface
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function SMMS_API($image) {
 | 
					function SMMS_API($image)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    $client_id = akina_option('smms_client_id');
 | 
					    $client_id = akina_option('smms_client_id');
 | 
				
			||||||
    $upload_url = "https://sm.ms/api/v2/upload";
 | 
					    $upload_url = "https://sm.ms/api/v2/upload";
 | 
				
			||||||
    $filename = $image['cmt_img_file']['name'];
 | 
					    $filename = $image['cmt_img_file']['name'];
 | 
				
			||||||
| 
						 | 
					@ -182,7 +243,7 @@ function SMMS_API($image) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $args = array(
 | 
					    $args = array(
 | 
				
			||||||
        'headers' => $headers,
 | 
					        'headers' => $headers,
 | 
				
			||||||
        'body' => $fields
 | 
					        'body' => $fields,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $response = wp_remote_post($upload_url, $args);
 | 
					    $response = wp_remote_post($upload_url, $args);
 | 
				
			||||||
| 
						 | 
					@ -222,7 +283,8 @@ function SMMS_API($image) {
 | 
				
			||||||
 * @rest api接口路径:https://sakura.2heng.xin/wp-json/sakura/v1/cache_search/json
 | 
					 * @rest api接口路径:https://sakura.2heng.xin/wp-json/sakura/v1/cache_search/json
 | 
				
			||||||
 * @可在cache_search_json()函数末尾通过设置 HTTP header 控制 json 缓存时间
 | 
					 * @可在cache_search_json()函数末尾通过设置 HTTP header 控制 json 缓存时间
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function cache_search_json() {
 | 
					function cache_search_json()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    $vowels = array("[", "{", "]", "}", "<", ">", "\r\n", "\r", "\n", "-", "'", '"', '`', " ", ":", ";", '\\', "  ", "toc");
 | 
					    $vowels = array("[", "{", "]", "}", "<", ">", "\r\n", "\r", "\n", "-", "'", '"', '`', " ", ":", ";", '\\', "  ", "toc");
 | 
				
			||||||
    $regex = <<<EOS
 | 
					    $regex = <<<EOS
 | 
				
			||||||
/<\/?[a-zA-Z]+("[^"]*"|'[^']*'|[^'">])*>|begin[\S\s]*\/begin|hermit[\S\s]*\/hermit|img[\S\s]*\/img|{{.*?}}|:.*?:/m
 | 
					/<\/?[a-zA-Z]+("[^"]*"|'[^']*'|[^'">])*>|begin[\S\s]*\/begin|hermit[\S\s]*\/hermit|img[\S\s]*\/img|{{.*?}}|:.*?:/m
 | 
				
			||||||
| 
						 | 
					@ -230,7 +292,7 @@ EOS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $posts = new WP_Query('posts_per_page=-1&post_status=publish&post_type=post');
 | 
					    $posts = new WP_Query('posts_per_page=-1&post_status=publish&post_type=post');
 | 
				
			||||||
    while ($posts->have_posts()): $posts->the_post();
 | 
					    while ($posts->have_posts()): $posts->the_post();
 | 
				
			||||||
    $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()))) . '},';
 | 
					        $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()))) . '},';
 | 
				
			||||||
    endwhile;
 | 
					    endwhile;
 | 
				
			||||||
    wp_reset_postdata();
 | 
					    wp_reset_postdata();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -268,7 +330,7 @@ EOS;
 | 
				
			||||||
    $result->set_headers(
 | 
					    $result->set_headers(
 | 
				
			||||||
        array(
 | 
					        array(
 | 
				
			||||||
            'Content-Type' => 'application/json',
 | 
					            'Content-Type' => 'application/json',
 | 
				
			||||||
            'Cache-Control' => 'max-age=3600'// json 缓存控制
 | 
					            'Cache-Control' => 'max-age=3600', // json 缓存控制
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,8 +13,8 @@ mashiro_option.site_name = "<?php echo akina_option('site_name', ''); ?>";
 | 
				
			||||||
mashiro_option.author_name = "<?php echo akina_option('author_name', ''); ?>";
 | 
					mashiro_option.author_name = "<?php echo akina_option('author_name', ''); ?>";
 | 
				
			||||||
mashiro_option.template_url = "<?php echo get_template_directory_uri(); ?>";
 | 
					mashiro_option.template_url = "<?php echo get_template_directory_uri(); ?>";
 | 
				
			||||||
mashiro_option.site_url = "<?php echo site_url(); ?>";
 | 
					mashiro_option.site_url = "<?php echo site_url(); ?>";
 | 
				
			||||||
mashiro_option.qq_api_url = "https://api.2heng.xin/qqinfo/"; 
 | 
					mashiro_option.qq_api_url = "<?php echo site_url(); ?>/wp-json/sakura/v1/qqinfo/json"; 
 | 
				
			||||||
mashiro_option.qq_avatar_api_url = "https://api.2heng.xin/qqinfo/";
 | 
					// mashiro_option.qq_avatar_api_url = "https://api.2heng.xin/qqinfo/";
 | 
				
			||||||
mashiro_option.live_search = <?php if ( akina_option('live_search') ){ echo 'true'; } else { echo 'false'; } ?>;
 | 
					mashiro_option.live_search = <?php if ( akina_option('live_search') ){ echo 'true'; } else { echo 'false'; } ?>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<?php if( akina_option('sakura_skin_bg' )){ $bg_arry=explode(",", akina_option('sakura_skin_bg' ));?>
 | 
					<?php if( akina_option('sakura_skin_bg' )){ $bg_arry=explode(",", akina_option('sakura_skin_bg' ));?>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -875,12 +875,10 @@ function getqqinfo() {
 | 
				
			||||||
        var qq = cached.filter('#author').val();
 | 
					        var qq = cached.filter('#author').val();
 | 
				
			||||||
        $.ajax({
 | 
					        $.ajax({
 | 
				
			||||||
            type: 'get',
 | 
					            type: 'get',
 | 
				
			||||||
            url: mashiro_option.qq_api_url + '?type=getqqnickname&qq=' + qq,
 | 
					            url: mashiro_option.qq_api_url + '?qq=' + qq + '&_wpnonce=' + Poi.nonce,
 | 
				
			||||||
            dataType: 'jsonp',
 | 
					            dataType: 'json',
 | 
				
			||||||
            jsonp: 'callback',
 | 
					 | 
				
			||||||
            jsonpCallback: 'portraitCallBack',
 | 
					 | 
				
			||||||
            success: function (data) {
 | 
					            success: function (data) {
 | 
				
			||||||
                cached.filter('#author').val(data[qq][6]);
 | 
					                cached.filter('#author').val(data.name);
 | 
				
			||||||
                cached.filter('#email').val($.trim(qq) + '@qq.com');
 | 
					                cached.filter('#email').val($.trim(qq) + '@qq.com');
 | 
				
			||||||
                if (mashiro_option.qzone_autocomplete) {
 | 
					                if (mashiro_option.qzone_autocomplete) {
 | 
				
			||||||
                    cached.filter('#url').val('https://user.qzone.qq.com/' + $.trim(qq));
 | 
					                    cached.filter('#url').val('https://user.qzone.qq.com/' + $.trim(qq));
 | 
				
			||||||
| 
						 | 
					@ -892,12 +890,15 @@ function getqqinfo() {
 | 
				
			||||||
                    $('.qq-check').css('display', 'block');
 | 
					                    $('.qq-check').css('display', 'block');
 | 
				
			||||||
                    $('.gravatar-check').css('display', 'none');
 | 
					                    $('.gravatar-check').css('display', 'none');
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                setCookie('user_author', data[qq][6], 30);
 | 
					                setCookie('user_author', data.name, 30);
 | 
				
			||||||
                setCookie('user_qq', qq, 30);
 | 
					                setCookie('user_qq', qq, 30);
 | 
				
			||||||
                setCookie('is_user_qq', 'yes', 30);
 | 
					                setCookie('is_user_qq', 'yes', 30);
 | 
				
			||||||
                setCookie('user_qq_email', qq + '@qq.com', 30);
 | 
					                setCookie('user_qq_email', qq + '@qq.com', 30);
 | 
				
			||||||
                setCookie('user_email', qq + '@qq.com', 30);
 | 
					                setCookie('user_email', qq + '@qq.com', 30);
 | 
				
			||||||
                emailAddressFlag = cached.filter('#email').val();
 | 
					                emailAddressFlag = cached.filter('#email').val();
 | 
				
			||||||
 | 
					                /***/
 | 
				
			||||||
 | 
					                $('div.comment-user-avatar img').attr('src', data.avatar);
 | 
				
			||||||
 | 
					                setCookie('user_avatar', data.avatar, 30);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            error: function () {
 | 
					            error: function () {
 | 
				
			||||||
                cached.filter('#qq').val('');
 | 
					                cached.filter('#qq').val('');
 | 
				
			||||||
| 
						 | 
					@ -907,19 +908,7 @@ function getqqinfo() {
 | 
				
			||||||
                setCookie('user_qq', '', 30);
 | 
					                setCookie('user_qq', '', 30);
 | 
				
			||||||
                setCookie('user_email', cached.filter('#email').val(), 30);
 | 
					                setCookie('user_email', cached.filter('#email').val(), 30);
 | 
				
			||||||
                setCookie('user_avatar', get_gravatar(cached.filter('#email').val(), 80), 30);
 | 
					                setCookie('user_avatar', get_gravatar(cached.filter('#email').val(), 80), 30);
 | 
				
			||||||
            }
 | 
					                /***/
 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        $.ajax({
 | 
					 | 
				
			||||||
            type: 'get',
 | 
					 | 
				
			||||||
            url: mashiro_option.qq_avatar_api_url + '?type=getqqavatar&qq=' + qq,
 | 
					 | 
				
			||||||
            dataType: 'jsonp',
 | 
					 | 
				
			||||||
            jsonp: 'callback',
 | 
					 | 
				
			||||||
            jsonpCallback: 'qqavatarCallBack',
 | 
					 | 
				
			||||||
            success: function (data) {
 | 
					 | 
				
			||||||
                $('div.comment-user-avatar img').attr('src', data[qq]);
 | 
					 | 
				
			||||||
                setCookie('user_avatar', data[qq], 30);
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            error: function () {
 | 
					 | 
				
			||||||
                cached.filter('#qq,#email,#url').val('');
 | 
					                cached.filter('#qq,#email,#url').val('');
 | 
				
			||||||
                if (!cached.filter('#qq').val()) {
 | 
					                if (!cached.filter('#qq').val()) {
 | 
				
			||||||
                    $('.qq-check').css('display', 'none');
 | 
					                    $('.qq-check').css('display', 'none');
 | 
				
			||||||
| 
						 | 
					@ -930,6 +919,27 @@ function getqqinfo() {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					        // $.ajax({
 | 
				
			||||||
 | 
					        //     type: 'get',
 | 
				
			||||||
 | 
					        //     url: mashiro_option.qq_avatar_api_url + '?type=getqqavatar&qq=' + qq,
 | 
				
			||||||
 | 
					        //     dataType: 'jsonp',
 | 
				
			||||||
 | 
					        //     jsonp: 'callback',
 | 
				
			||||||
 | 
					        //     jsonpCallback: 'qqavatarCallBack',
 | 
				
			||||||
 | 
					        //     success: function (data) {
 | 
				
			||||||
 | 
					        //         $('div.comment-user-avatar img').attr('src', data[qq]);
 | 
				
			||||||
 | 
					        //         setCookie('user_avatar', data[qq], 30);
 | 
				
			||||||
 | 
					        //     },
 | 
				
			||||||
 | 
					        //     error: function () {
 | 
				
			||||||
 | 
					        //         cached.filter('#qq,#email,#url').val('');
 | 
				
			||||||
 | 
					        //         if (!cached.filter('#qq').val()) {
 | 
				
			||||||
 | 
					        //             $('.qq-check').css('display', 'none');
 | 
				
			||||||
 | 
					        //             $('.gravatar-check').css('display', 'block');
 | 
				
			||||||
 | 
					        //             setCookie('user_qq', '', 30);
 | 
				
			||||||
 | 
					        //             $('div.comment-user-avatar img').attr('src', get_gravatar(cached.filter('#email').val(), 80));
 | 
				
			||||||
 | 
					        //             setCookie('user_avatar', get_gravatar(cached.filter('#email').val(), 80), 30);
 | 
				
			||||||
 | 
					        //         }
 | 
				
			||||||
 | 
					        //     }
 | 
				
			||||||
 | 
					        // });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    if (getCookie('user_avatar') && getCookie('user_email') && getCookie('is_user_qq') == 'no' && !getCookie('user_qq_email')) {
 | 
					    if (getCookie('user_avatar') && getCookie('user_email') && getCookie('is_user_qq') == 'no' && !getCookie('user_qq_email')) {
 | 
				
			||||||
        $('div.comment-user-avatar img').attr('src', getCookie('user_avatar'));
 | 
					        $('div.comment-user-avatar img').attr('src', getCookie('user_avatar'));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "python.pythonPath": "C:\\Users\\Mashiro\\AppData\\Local\\Programs\\Python\\Python38\\python.exe"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,45 @@
 | 
				
			||||||
 | 
					封面图生成工具
 | 
				
			||||||
 | 
					===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 依赖
 | 
				
			||||||
 | 
					Python3
 | 
				
			||||||
 | 
					PIL (Pillow)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 安装依赖
 | 
				
			||||||
 | 
					安装 Python: <https://docs.python.org/zh-cn/3.7/using/index.html>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					安装 PIL:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					# Linix/Mac Terminal
 | 
				
			||||||
 | 
					pip install Pillow
 | 
				
			||||||
 | 
					# 如果也安装了 Python 2,需要指定 pip 版本:
 | 
				
			||||||
 | 
					pip3 install Pillow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Windows Powershell 或者 CMD
 | 
				
			||||||
 | 
					pip install Pillow
 | 
				
			||||||
 | 
					# 如果也安装了 Python 2,需要指定 pip 版本:
 | 
				
			||||||
 | 
					pip3 install Pillow
 | 
				
			||||||
 | 
					# 如果提示权限不足([WinError 5] Access is denied),请运行:
 | 
				
			||||||
 | 
					pip install Pillow --user
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 运行
 | 
				
			||||||
 | 
					把图片文件放到 `gallary` 目录,Windows 可直接双击 manifest.py,或者和其他操作系统一样,在 Terminal、Powershell、CMD 中运行:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					# 切换到 manifest.py 所在目录:
 | 
				
			||||||
 | 
					cd /path/to/manifest/
 | 
				
			||||||
 | 
					python manifest.py
 | 
				
			||||||
 | 
					# 如果也安装了 Python 2,需要指定 Python 版本:
 | 
				
			||||||
 | 
					python3 manifest.py
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GUI 程序开发中,除了以上运行 manifest.py 的方法以外,也可直接运行 qt.py 启动可视化窗口,需要安装 PyQT5:
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					pip3 install PyQt5
 | 
				
			||||||
 | 
					python3 qt.py
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### TODO
 | 
				
			||||||
 | 
					shell/batch 自动安装依赖、自动删除过期文件、压缩图片、GitHub API push、release
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					from .manifest import *
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 131 KiB  | 
| 
		 After Width: | Height: | Size: 248 KiB  | 
| 
		 After Width: | Height: | Size: 55 KiB  | 
| 
		 After Width: | Height: | Size: 119 KiB  | 
| 
		 After Width: | Height: | Size: 50 KiB  | 
| 
		 After Width: | Height: | Size: 102 KiB  | 
| 
		 After Width: | Height: | Size: 17 KiB  | 
| 
		 After Width: | Height: | Size: 200 KiB  | 
| 
		 After Width: | Height: | Size: 20 KiB  | 
| 
		 After Width: | Height: | Size: 43 KiB  | 
| 
		 After Width: | Height: | Size: 9.7 KiB  | 
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					{"19313b0d62b27c8ba022f60fbfedd5ee": {"source": "beyond_by_auroralion-dan5njb.jpg", "jpeg": ["jpeg/19313b0d62b27c8ba022f60fbfedd5ee.jpeg", "jpeg/19313b0d62b27c8ba022f60fbfedd5ee.th.jpeg"], "webp": ["webp/19313b0d62b27c8ba022f60fbfedd5ee.webp", "webp/19313b0d62b27c8ba022f60fbfedd5ee.th.webp"]}, "783bf161f47b32882f0e962fd4064de7": {"source": "pixar_up_movie_balloons_desktop_1920x1080_hd-wallpaper-507967.jpg", "jpeg": ["jpeg/783bf161f47b32882f0e962fd4064de7.jpeg", "jpeg/783bf161f47b32882f0e962fd4064de7.th.jpeg"], "webp": ["webp/783bf161f47b32882f0e962fd4064de7.webp", "webp/783bf161f47b32882f0e962fd4064de7.th.webp"]}, "e9f33c2c502ab43804964ce7edd431f9": {"source": "\u6d77\u306e\u7a7a(56993195)_by_\u590fT.jpg", "jpeg": ["jpeg/e9f33c2c502ab43804964ce7edd431f9.jpeg", "jpeg/e9f33c2c502ab43804964ce7edd431f9.th.jpeg"], "webp": ["webp/e9f33c2c502ab43804964ce7edd431f9.webp", "webp/e9f33c2c502ab43804964ce7edd431f9.th.webp"]}}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,89 @@
 | 
				
			||||||
 | 
					# coding=utf-8
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					Created on Apr 23, 2018
 | 
				
			||||||
 | 
					Desc: Webp convertor
 | 
				
			||||||
 | 
					@author: Mashiro https://2heng.xin
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					import base64
 | 
				
			||||||
 | 
					import hashlib
 | 
				
			||||||
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Single(object):
 | 
				
			||||||
 | 
					  def __init__(self, file, manifest):
 | 
				
			||||||
 | 
					    self.file = file
 | 
				
			||||||
 | 
					    self.mani = manifest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def hash(self):
 | 
				
			||||||
 | 
					    hasher = hashlib.md5()
 | 
				
			||||||
 | 
					    with open('gallary/' + self.file, 'rb') as afile:
 | 
				
			||||||
 | 
					      buf = afile.read()
 | 
				
			||||||
 | 
					      hasher.update(buf)
 | 
				
			||||||
 | 
					    self.hash = hasher.hexdigest()
 | 
				
			||||||
 | 
					    self.jpeg = 'jpeg/' + self.hash + '.jpeg'
 | 
				
			||||||
 | 
					    self.webp = 'webp/' + self.hash + '.webp'
 | 
				
			||||||
 | 
					    self.jpeg_th = 'jpeg/' + self.hash + '.th.jpeg'
 | 
				
			||||||
 | 
					    self.webp_th = 'webp/' + self.hash + '.th.webp'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def optimize(self):
 | 
				
			||||||
 | 
					    im = Image.open('gallary/' + self.file).convert('RGB')
 | 
				
			||||||
 | 
					    im.save(self.jpeg, 'JPEG') # todo: TinyPNG API
 | 
				
			||||||
 | 
					    im.save(self.webp, 'WEBP')
 | 
				
			||||||
 | 
					    im.thumbnail((450, 300))
 | 
				
			||||||
 | 
					    im.save(self.jpeg_th, 'JPEG')  # todo: TinyPNG API
 | 
				
			||||||
 | 
					    im.save(self.webp_th, 'WEBP')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def manifest(self):
 | 
				
			||||||
 | 
					    self.mani[self.hash] = {
 | 
				
			||||||
 | 
					      'source': self.file,
 | 
				
			||||||
 | 
					      'jpeg': [self.jpeg, self.jpeg_th],
 | 
				
			||||||
 | 
					      'webp': [self.webp, self.webp_th]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #这个最好新建一个类
 | 
				
			||||||
 | 
					  def upload_manifest(self):
 | 
				
			||||||
 | 
					    username = input('Enter your username: ')
 | 
				
			||||||
 | 
					    password = input('Enter your password: ')
 | 
				
			||||||
 | 
					    url = input('Enter your rest api url: ')
 | 
				
			||||||
 | 
					    data_string = username + ':' + password
 | 
				
			||||||
 | 
					    token = base64.b64encode(data_string.encode()).decode('utf-8')
 | 
				
			||||||
 | 
					    headers = {
 | 
				
			||||||
 | 
					      'Authorization': 'Basic ' + token,
 | 
				
			||||||
 | 
					      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    files = {'manifest': open('manifest.json', mode="rb")}
 | 
				
			||||||
 | 
					    reply = requests.post(url, headers=headers, files=files)
 | 
				
			||||||
 | 
					    print(json.loads(reply.content)['message'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def main(self):
 | 
				
			||||||
 | 
					    self.hash()
 | 
				
			||||||
 | 
					    # if os.path.exists(self.jpeg) and os.path.exists(self.webp):
 | 
				
			||||||
 | 
					    self.optimize()
 | 
				
			||||||
 | 
					    self.thumbnail()
 | 
				
			||||||
 | 
					    self.manifest()
 | 
				
			||||||
 | 
					    return self.mani
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					  onlyfiles = [f for f in os.listdir('gallary') if os.path.isfile(os.path.join('gallary', f))]
 | 
				
			||||||
 | 
					  id = 1
 | 
				
			||||||
 | 
					  Manifest = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for f in onlyfiles:
 | 
				
			||||||
 | 
					      worker = Single(f, Manifest)
 | 
				
			||||||
 | 
					      Manifest = worker.main()
 | 
				
			||||||
 | 
					      print(str(id) + '/' + str(len(onlyfiles)))
 | 
				
			||||||
 | 
					      id += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  with open('manifest.json', 'w+') as json_file:
 | 
				
			||||||
 | 
					    json.dump(Manifest, json_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  up_json = Single(f, Manifest)
 | 
				
			||||||
 | 
					  up_json.upload_manifest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					  main()
 | 
				
			||||||
 | 
					  key = input('`manifest.json` saved. Press any key to quit.') 
 | 
				
			||||||
 | 
					  quit()
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,89 @@
 | 
				
			||||||
 | 
					#!/usr/bin/python3
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Created on Nov 29, 2019
 | 
				
			||||||
 | 
					Desc: Webp convertor QT
 | 
				
			||||||
 | 
					@author: Mashiro @ https://2heng.xin
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					from PyQt5.QtWidgets import QMainWindow, QWidget, QApplication, QPushButton, QMessageBox, QDesktopWidget, QGridLayout
 | 
				
			||||||
 | 
					from PyQt5.QtCore import QCoreApplication
 | 
				
			||||||
 | 
					from PyQt5.QtGui import QIcon
 | 
				
			||||||
 | 
					from manifest import main as manifest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MainWindow(QMainWindow):
 | 
				
			||||||
 | 
					  def __init__(self):
 | 
				
			||||||
 | 
					    super().__init__()
 | 
				
			||||||
 | 
					    self.initUI()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def initUI(self):
 | 
				
			||||||
 | 
					    self.statusBar().showMessage('Ready')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self.BtnWid = QWidget(self)
 | 
				
			||||||
 | 
					    self.setCentralWidget(self.BtnWid)
 | 
				
			||||||
 | 
					    grid = QGridLayout()
 | 
				
			||||||
 | 
					    self.BtnWid.setLayout(grid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    names = ['Generate manifest.json',
 | 
				
			||||||
 | 
					             'Pull from GitHub',
 | 
				
			||||||
 | 
					             'Push to GitHub',
 | 
				
			||||||
 | 
					             'Release on GitHub',
 | 
				
			||||||
 | 
					             'Push manifest.json to WordPress',
 | 
				
			||||||
 | 
					             'About and Turtor']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    actions = [self.Action_1,
 | 
				
			||||||
 | 
					               self.Action_0,
 | 
				
			||||||
 | 
					               self.Action_0,
 | 
				
			||||||
 | 
					               self.Action_0,
 | 
				
			||||||
 | 
					               self.Action_0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    positions = [(i, j) for i in range(6) for j in range(1)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for position, name, action in zip(positions, names, actions):
 | 
				
			||||||
 | 
					      if name == '':
 | 
				
			||||||
 | 
					        continue
 | 
				
			||||||
 | 
					      button = QPushButton(name)
 | 
				
			||||||
 | 
					      button.clicked.connect(action)
 | 
				
			||||||
 | 
					      grid.addWidget(button, *position)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # self.resize(500, 500)
 | 
				
			||||||
 | 
					    self.center()
 | 
				
			||||||
 | 
					    self.setWindowTitle('Manifest Generator')
 | 
				
			||||||
 | 
					    self.setWindowIcon(QIcon('icon.png'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def Action_0(self):
 | 
				
			||||||
 | 
					    sender = self.sender()
 | 
				
			||||||
 | 
					    self.statusBar().showMessage('"' + sender.text() + '" was pressed')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #Generate manifest.json
 | 
				
			||||||
 | 
					  def Action_1(self):
 | 
				
			||||||
 | 
					    # self.statusBar().showMessage('Processing...')
 | 
				
			||||||
 | 
					    # time.sleep(1)
 | 
				
			||||||
 | 
					    manifest()
 | 
				
			||||||
 | 
					    self.statusBar().showMessage('`manifest.json` saved.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def center(self):
 | 
				
			||||||
 | 
					    qr = self.frameGeometry()
 | 
				
			||||||
 | 
					    cp = QDesktopWidget().availableGeometry().center()
 | 
				
			||||||
 | 
					    qr.moveCenter(cp)
 | 
				
			||||||
 | 
					    self.move(qr.topLeft())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def closeEvent(self, event):
 | 
				
			||||||
 | 
					    reply = QMessageBox.question(self, 'Message',
 | 
				
			||||||
 | 
					                                 "Are you sure to quit?", QMessageBox.Yes |
 | 
				
			||||||
 | 
					                                 QMessageBox.No, QMessageBox.No)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if reply == QMessageBox.Yes:
 | 
				
			||||||
 | 
					      event.accept()
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					      event.ignore()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  app = QApplication(sys.argv)
 | 
				
			||||||
 | 
					  ex = MainWindow()
 | 
				
			||||||
 | 
					  sys.exit(app.exec_())
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 13 KiB  | 
| 
		 After Width: | Height: | Size: 89 KiB  | 
| 
		 After Width: | Height: | Size: 18 KiB  | 
| 
		 After Width: | Height: | Size: 190 KiB  | 
| 
		 After Width: | Height: | Size: 5.2 KiB  | 
| 
		 After Width: | Height: | Size: 24 KiB  |