公开API
public_api_add_comment
- 用于为一篇文章添加评论
请求路径: /api/v1/add_comment
请求方式: POST
传入参数 (JSON
):
verify_token
string
: 通过验证后得到的token,由Cloudflare turnsite
或google reCaptcha
生成.article_id
string
: 标识文章唯一ID,用于添加评论的文章id.content
string
: 评论内容,在contentAdvisor_config
为ture且filter_comment
为true时仅支持普通文本,在filter_comment
或contentAdvisor_config
为false时支持HTML DOM元素注入(会导致XSS攻击).author
string
: 作者.email
string
: 邮箱,仅用于记录,不会被渲染进comment模板中.reply_to
string
: 回复的评论ID,为空则不设置为回复.
传出:
header
:200|500|403|404|405|429body
:OK
示例:
> POST /api/v1/add_comment HTTP/1.1
>
> {
> "verify_token":"token",
> "article_id":"13cc99f4328b70cff5c7c1adea30c89f",
> "author":"Unicode",
> "email":"unicode@un1c0de.com",
> "content":"unicodeAddCommentTest"
> }
>
< HTTP/1.1 200 OK
<
< OK
后端API
在和后端进行通信时,需要获取三个参数
backend_path
: 后端通信url,即此后用于和后端通信的path地址encryptKey
: 加密密钥access_token
: 通讯密钥
其中 backend_url
和token
由用户输入,enncryptKey
由liteblog根据backend_path
和access_token
生成,并加入到rendered
map中,可以在渲染的文件中用{{rendered:token_encrypt_key}}
获取
后续所有API中的Token
均为加密后的token
token不可逆生成函数:
传入用户token,生成和后端通信token
- js version
function generateEncryptToken(token) {
var encryptKey = `{{rendered:token_encrypt_key}}`;
const timestamp = parseInt((new Date().getTime())/10000); // 时间梯度10s
// console.log(timestamp);
const timestampB64 = btoa(timestamp.toString());
// console.log(timestampB64);
encryptKey = encryptKey + timestampB64;
console.log(token + "|" + encryptKey)
let tokenArray = Array.from(btoa(token + "|" + encryptKey));
const getRandomChar = (seed) => String.fromCharCode(33 + (seed % 94));
for (let i = 0; i < encryptKey.length; i++) {
const charCode = encryptKey.charCodeAt(i);
const operation = charCode % 5;
switch (operation) {
case 0:
tokenArray.unshift(getRandomChar(charCode + i));
break;
case 1:
if (tokenArray.length > 0) {
const pos = (charCode * i) % tokenArray.length;
tokenArray[pos] = getRandomChar(charCode ^ tokenArray[pos].charCodeAt(0));
}
break;
case 2:
tokenArray.splice(charCode % (tokenArray.length + 1), 0,
getRandomChar(charCode),
getRandomChar(charCode + 997)
);
break;
case 3:
if (tokenArray.length > 1) {
const pos1 = charCode % tokenArray.length;
const pos2 = tokenArray.length - 1 - pos1;
[tokenArray[pos1], tokenArray[pos2]] = [tokenArray[pos2], tokenArray[pos1]];
}
break;
default:
const pseudo = ['==', '=', '=A', 'B='][charCode % 4];
tokenArray.push(...Array.from(pseudo));
}
}
const finalShuffle = [];
while (tokenArray.length > 0) {
const randIndex = (encryptKey.length * tokenArray.length) % tokenArray.length;
finalShuffle.push(tokenArray.splice(randIndex, 1)[0]);
}
return finalShuffle.join('');
}
- go version
注意: 以下的golang示例是后端示例,用于生成用于验证的token,所以需要传入三个参数,用于生成当前时间±20s的token(5个),进行对比.
func generateEncryptToken(token string, encryptKey string, timestampBase64 string) string {
encryptKey = encryptKey + timestampBase64
data := []byte(token + "|" + encryptKey)
encoded := base64.StdEncoding.EncodeToString(data)
// fmt.Printf("encoded: %s\n", encoded)
tokenArray := []byte(encoded)
getRandomChar := func(seed int) byte {
return byte(33 + (seed % 94))
}
for i := 0; i < len(encryptKey); i++ {
charCode := int(encryptKey[i])
operation := charCode % 5
switch operation {
case 0:
tokenArray = append([]byte{getRandomChar(charCode + i)}, tokenArray...)
case 1:
if len(tokenArray) > 0 {
pos := (charCode * i) % len(tokenArray)
tokenArray[pos] = getRandomChar(charCode ^ int(tokenArray[pos]))
}
case 2:
insertPos := charCode % (len(tokenArray) + 1)
char1 := getRandomChar(charCode)
char2 := getRandomChar(charCode + 997)
tokenArray = append(tokenArray[:insertPos], append([]byte{char1, char2}, tokenArray[insertPos:]...)...)
case 3:
if len(tokenArray) > 1 {
pos1 := charCode % len(tokenArray)
pos2 := len(tokenArray) - 1 - pos1
tokenArray[pos1], tokenArray[pos2] = tokenArray[pos2], tokenArray[pos1]
}
default:
pseudo := [...]string{"==", "=", "=A", "B="}[charCode%4]
tokenArray = append(tokenArray, []byte(pseudo)...)
}
}
finalShuffle := make([]byte, 0, len(tokenArray))
for len(tokenArray) > 0 {
randIndex := (len(encryptKey) * len(tokenArray)) % len(tokenArray)
finalShuffle = append(finalShuffle, tokenArray[randIndex])
tokenArray = append(tokenArray[:randIndex], tokenArray[randIndex+1:]...)
}
return string(finalShuffle)
}
card类
edit_order
- 此接口用于编辑主页卡片
order
(顺序)字段
请求路径:/{backendPath}/edit_order
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokenchanges
[]JSON
{cardID
string
: 需要修改的卡片ID
order
int
: 修改后的order
- }
- 注:
changes
为数组对象类型
传出 :
header
: 200|400|403|405|500body
:OK
delete_card
- 此接口用于删除主页卡片
请求路径:/{backendPath}/delete_card
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokencardID
string
: 需要删除的卡片ID
传出 :
header
: 200|400|403|405|500body
:OK
add_card
- 此接口用于添加主页卡片
请求路径:/{backendPath}/add_card
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokencard
map[string]string
: 卡片信息JSON
传出 :
header
: 200|400|403|405|500body
:OK
get_card
- 此接口用于获取主页卡片信息
请求路径:/{backendPath}/get_card
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokencardID
string
: 需要获取的卡片ID
传出 :
header
: 200|400|403|405|500body
map[string]string
: 卡片信息的JSON格式代码
get_all_cards
- 此接口用于获取所有主页卡片信息
请求路径:/{backendPath}/get_all_cards
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的token
传出 :
header
: 200|400|403|405|500body
[]card
: 卡片信息的JSON数组格式代码 例:[{"id": "1","order": "1","tags": "go tag1 tag2","template": "card_template_classical"}]
edit_card
- 此接口用于编辑卡片信息
请求路径:/{backendPath}/edit_card
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokencard
map[string]string
: 卡片信息的JSON代码
注:card
字段的map中必须含有id
传出 :
header
: 200|400|403|405|500body
:OK
article类
add_article
- 此接口用于添加一篇文章
请求路径:/{backendPath}/add_article
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokenarticle
JSON
{title
string
: 文章标题
content
string
: 文章内容的markdown格式
content_html
string
: 文章内容的HTML渲染后格式
author
string
: 作者
}
传出 :
header
: 200|400|403|405|500body
JSON
{article_id
: 添加完成后返回生成的文章ID
}
edit_article
- 此接口用于编辑一篇文章
请求路径:/{backendPath}/edit_article
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokenarticle
JSON
{article_id
string
: 文章ID
title
string
: 文章标题
content
string
: 文章内容的markdown格式
content_html
string
: 文章内容的HTML渲染后格式
author
string
: 作者
}
传出 :
header
: 200|400|403|405|500body
:OK
get_article
- 此接口用于获取一篇文章的信息
请求路径:/{backendPath}/get_article
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokenarticle_id
string
: 需要获取的文章id
传出 :
header
: 200|400|403|405|500body
JSON
{title
string
: 文章标题
content
string
: 文章内容的markdown格式
content_html
string
: 文章内容的HTML渲染后格式
edit_date
string
: 文章的编辑日期
pub_date
string
: 文章的发布日期
author
string
: 作者
comment
[] 以后再填坑
}
get_all_article_id
- 此接口用于获取所有文章id
请求路径:/{backendPath}/get_all_article_id
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的token
传出 :
header
: 200|400|403|405|500body
[]string
: 所有文章ID的数组 例:["articleID1","articleID2"]
delete_article
- 此接口用于删除一条评论
请求路径:/{backendPath}/delete_comment
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokenarticle_id
string
: 需要删除的文章idcomment_id
string
: 需要删除的评论id
传出 :
header
: 200|400|403|405|500body
:OK
delete_comment
- 此接口用于删除一篇文章
请求路径:/{backendPath}/delete_article
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokenarticle_id
string
: 需要删除的文章id
传出 :
header
: 200|400|403|405|500body
:OK
设置类
get_custom_settings
- 此接口用于获取个性化设置字段
请求路径:/{backendPath}/get_custom_settings
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的token
传出 :
header
: 200|400|403|405|500body
JSON
{custom_script
string
: 当前的自定义脚本
custom_style
string
: 当前的自定义样式
global_settings
map[string]string
: 全局设置项
}
edit_custom_settings
- 此接口用于填写个性化设置字段
请求路径:/{backendPath}/edit_custom_settings
请求方式: POST
传入参数 (JSON
):
token
string
: 加密后的tokencustom_settings
JSON
{global_settings
map[string]string
: 更新的全局设置
custom_script
string
: 更新后的自定义脚本
custom_settings
string
: 更新后的自定义设置
}
传出 :
header
: 200|400|403|405|500body
:OK