Merge branch 'dev' into pr-branch

This commit is contained in:
Mashiro 2019-12-03 21:33:14 +08:00 committed by GitHub
commit a82f353b36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 339 additions and 39 deletions

View File

@ -20,16 +20,75 @@ add_action('rest_api_init', function () {
'methods' => 'GET',
'callback' => 'feature_gallery',
));
register_rest_route('sakura/v1', '/image/json', array(
register_rest_route('sakura/v1', '/image/manifest', array(
'methods' => 'POST',
'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
*/
function upload_image(WP_REST_Request $request) {
function upload_image(WP_REST_Request $request)
{
// see: https://developer.wordpress.org/rest-api/requests/
// handle file params $file === $_FILES
@ -41,8 +100,7 @@ function upload_image(WP_REST_Request $request) {
*/
// $file = $request->get_file_params();
if (!check_ajax_referer('wp_rest', '_wpnonce', false)) {
$output = array(
'status' => 403,
$output = array('status' => 403,
'success' => false,
'message' => 'Unauthorized client.',
'link' => "https://view.moezx.cc/images/2019/11/14/step04.md.png",
@ -68,7 +126,7 @@ function upload_image(WP_REST_Request $request) {
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'));
return $result;
}
@ -76,13 +134,14 @@ function upload_image(WP_REST_Request $request) {
/**
* Chevereto upload interface
*/
function Chevereto_API($image) {
$upload_url = akina_option('cheverto_url').'/api/1/upload';
function Chevereto_API($image)
{
$upload_url = akina_option('cheverto_url') . '/api/1/upload';
$args = array(
'body' => array(
'source' => base64_encode($image),
'key' => akina_option('chevereto_api_key')
)
'key' => akina_option('chevereto_api_key'),
),
);
$response = wp_remote_post($upload_url, $args);
@ -114,16 +173,17 @@ function Chevereto_API($image) {
/**
* Imgur upload interface
*/
function Imgur_API($image) {
function Imgur_API($image)
{
$client_id = akina_option('imgur_client_id');
$upload_url = akina_option('imgur_upload_image_proxy');
$args = array(
'headers' => array(
'Authorization' => 'Client-ID ' . $client_id
'Authorization' => 'Client-ID ' . $client_id,
),
'body' => array(
'image' => base64_encode($image)
)
'image' => base64_encode($image),
),
);
$response = wp_remote_post($upload_url, $args);
@ -155,7 +215,8 @@ function Imgur_API($image) {
/**
* smms upload interface
*/
function SMMS_API($image) {
function SMMS_API($image)
{
$client_id = akina_option('smms_client_id');
$upload_url = "https://sm.ms/api/v2/upload";
$filename = $image['cmt_img_file']['name'];
@ -182,7 +243,7 @@ function SMMS_API($image) {
$args = array(
'headers' => $headers,
'body' => $fields
'body' => $fields,
);
$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
* @可在cache_search_json()函数末尾通过设置 HTTP header 控制 json 缓存时间
*/
function cache_search_json() {
function cache_search_json()
{
$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
@ -268,7 +330,7 @@ EOS;
$result->set_headers(
array(
'Content-Type' => 'application/json',
'Cache-Control' => 'max-age=3600'// json 缓存控制
'Cache-Control' => 'max-age=3600', // json 缓存控制
)
);

View File

@ -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.template_url = "<?php echo get_template_directory_uri(); ?>";
mashiro_option.site_url = "<?php echo site_url(); ?>";
mashiro_option.qq_api_url = "https://api.2heng.xin/qqinfo/";
mashiro_option.qq_avatar_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.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' ));?>

View File

@ -875,12 +875,10 @@ function getqqinfo() {
var qq = cached.filter('#author').val();
$.ajax({
type: 'get',
url: mashiro_option.qq_api_url + '?type=getqqnickname&qq=' + qq,
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'portraitCallBack',
url: mashiro_option.qq_api_url + '?qq=' + qq + '&_wpnonce=' + Poi.nonce,
dataType: 'json',
success: function (data) {
cached.filter('#author').val(data[qq][6]);
cached.filter('#author').val(data.name);
cached.filter('#email').val($.trim(qq) + '@qq.com');
if (mashiro_option.qzone_autocomplete) {
cached.filter('#url').val('https://user.qzone.qq.com/' + $.trim(qq));
@ -892,12 +890,15 @@ function getqqinfo() {
$('.qq-check').css('display', 'block');
$('.gravatar-check').css('display', 'none');
}
setCookie('user_author', data[qq][6], 30);
setCookie('user_author', data.name, 30);
setCookie('user_qq', qq, 30);
setCookie('is_user_qq', 'yes', 30);
setCookie('user_qq_email', qq + '@qq.com', 30);
setCookie('user_email', qq + '@qq.com', 30);
emailAddressFlag = cached.filter('#email').val();
/***/
$('div.comment-user-avatar img').attr('src', data.avatar);
setCookie('user_avatar', data.avatar, 30);
},
error: function () {
cached.filter('#qq').val('');
@ -907,19 +908,7 @@ function getqqinfo() {
setCookie('user_qq', '', 30);
setCookie('user_email', cached.filter('#email').val(), 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('');
if (!cached.filter('#qq').val()) {
$('.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')) {
$('div.comment-user-avatar img').attr('src', getCookie('user_avatar'));

3
manifest/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"python.pythonPath": "C:\\Users\\Mashiro\\AppData\\Local\\Programs\\Python\\Python38\\python.exe"
}

45
manifest/README.md Normal file
View File

@ -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

1
manifest/__init__.py Normal file
View File

@ -0,0 +1 @@
from .manifest import *

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
manifest/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
manifest/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

1
manifest/manifest.json Normal file
View File

@ -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"]}}

89
manifest/manifest.py Normal file
View File

@ -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()

89
manifest/qt.py Normal file
View File

@ -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_())

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB