q-koa 7.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/app.js +1813 -0
- package/core/config.js +124 -0
- package/core/file/plugins/administrator/config.js +17 -0
- package/core/file/plugins/administrator/controller.js +264 -0
- package/core/file/plugins/administrator/model.js +53 -0
- package/core/file/plugins/administrator/validate.js +41 -0
- package/core/file/plugins/alipay/controller.js +68 -0
- package/core/file/plugins/alipay/validate.js +9 -0
- package/core/file/plugins/cache/service.js +16 -0
- package/core/file/plugins/cloudfunction/config.js +4 -0
- package/core/file/plugins/cloudfunction/model.js +15 -0
- package/core/file/plugins/common/controller.js +398 -0
- package/core/file/plugins/common/validate.js +47 -0
- package/core/file/plugins/douyin/config.js +3 -0
- package/core/file/plugins/douyin/controller.js +521 -0
- package/core/file/plugins/douyin/validate.js +40 -0
- package/core/file/plugins/douyin_user/config.js +15 -0
- package/core/file/plugins/douyin_user/model.js +72 -0
- package/core/file/plugins/good_sku/controller.js +80 -0
- package/core/file/plugins/h5_user/config.js +19 -0
- package/core/file/plugins/h5_user/model.js +71 -0
- package/core/file/plugins/lang/config.js +4 -0
- package/core/file/plugins/lang/model.js +15 -0
- package/core/file/plugins/language/config.js +5 -0
- package/core/file/plugins/language/model.js +54 -0
- package/core/file/plugins/log/config.js +25 -0
- package/core/file/plugins/log/controller.js +31 -0
- package/core/file/plugins/log/model.js +51 -0
- package/core/file/plugins/model/config.js +12 -0
- package/core/file/plugins/model/controller.js +69 -0
- package/core/file/plugins/model/model.js +169 -0
- package/core/file/plugins/model/service.js +218 -0
- package/core/file/plugins/model/validate.js +42 -0
- package/core/file/plugins/model_attributes/config.js +12 -0
- package/core/file/plugins/model_attributes/model.js +114 -0
- package/core/file/plugins/mp_user/config.js +19 -0
- package/core/file/plugins/mp_user/model.js +59 -0
- package/core/file/plugins/permission/config.js +15 -0
- package/core/file/plugins/permission/model.js +91 -0
- package/core/file/plugins/role/config.js +27 -0
- package/core/file/plugins/role/controller.js +26 -0
- package/core/file/plugins/role/model.js +58 -0
- package/core/file/plugins/role_permission/config.js +12 -0
- package/core/file/plugins/role_permission/controller.js +27 -0
- package/core/file/plugins/role_permission/model.js +24 -0
- package/core/file/plugins/routes/config.js +17 -0
- package/core/file/plugins/routes/controller.js +153 -0
- package/core/file/plugins/routes/model.js +70 -0
- package/core/file/plugins/routes/service.js +22 -0
- package/core/file/plugins/setting/afterExecute.js +14 -0
- package/core/file/plugins/setting/config.js +14 -0
- package/core/file/plugins/setting/controller.js +50 -0
- package/core/file/plugins/setting/model.js +118 -0
- package/core/file/plugins/setting/validate.js +42 -0
- package/core/file/plugins/system/controller.js +501 -0
- package/core/file/plugins/system/service.js +148 -0
- package/core/file/plugins/system/validate.js +40 -0
- package/core/file/plugins/todolist/config.js +31 -0
- package/core/file/plugins/todolist/model.js +69 -0
- package/core/file/plugins/toutiao/controller.js +201 -0
- package/core/file/plugins/toutiao_user/config.js +15 -0
- package/core/file/plugins/toutiao_user/model.js +66 -0
- package/core/file/plugins/user/afterExecute.js +38 -0
- package/core/file/plugins/user/config.js +9 -0
- package/core/file/plugins/user/controller.js +329 -0
- package/core/file/plugins/user/model.js +96 -0
- package/core/file/plugins/user/test.js +71 -0
- package/core/file/plugins/user/validate.js +44 -0
- package/core/file/plugins/video/config.js +3 -0
- package/core/file/plugins/video/controller.js +15 -0
- package/core/file/plugins/video/validate.js +12 -0
- package/core/file/plugins/weixin/config.js +3 -0
- package/core/file/plugins/weixin/controller.js +994 -0
- package/core/file/plugins/weixin/service.js +105 -0
- package/core/file/plugins/weixin/validate.js +111 -0
- package/core/file/services/aliSms.js +45 -0
- package/core/file/services/alipay.js +123 -0
- package/core/file/services/amap.js +95 -0
- package/core/file/services/card.js +24 -0
- package/core/file/services/config.js +38 -0
- package/core/file/services/douyin.js +151 -0
- package/core/file/services/email.js +45 -0
- package/core/file/services/express.js +37 -0
- package/core/file/services/geo.js +71 -0
- package/core/file/services/qqVideo.js +64 -0
- package/core/file/services/toutiao.js +102 -0
- package/core/file/services/weixin.js +79 -0
- package/core/file/services/weixinArticle.js +53 -0
- package/core/file/services/weixinCrypt.js +34 -0
- package/core/file/services/weixinMP.js +435 -0
- package/core/file/services/weixinPay.js +35 -0
- package/core/file/services/xml.js +33 -0
- package/core/file/task/shop/index.js +589 -0
- package/core/file/task/shop/static/562e45760a44632de6fa7219bab78cce.png +0 -0
- package/core/file/task/shop/static/d7aeaeb6bfd68f71a00a83c0f5548363.png +0 -0
- package/core/file/utils/index.js +61 -0
- package/core/middlewares.js +120 -0
- package/core/restc/.npminstall.done +1 -0
- package/core/restc/LICENSE +21 -0
- package/core/restc/README.md +48 -0
- package/core/restc/faas/index.html +1112 -0
- package/core/restc/faas/index.txt +31 -0
- package/core/restc/faas/install_production.sh +6 -0
- package/core/restc/index.d.ts +7 -0
- package/core/restc/index.js +9 -0
- package/core/restc/lib/express.js +7 -0
- package/core/restc/lib/hapi.js +17 -0
- package/core/restc/lib/hapiLegacy.js +15 -0
- package/core/restc/lib/index.js +46 -0
- package/core/restc/lib/koa.js +9 -0
- package/core/restc/lib/koa2.js +9 -0
- package/core/restc/lib/utils/gateway.js +51 -0
- package/core/restc/package.json +41 -0
- package/core/validator.js +15 -0
- package/index.js +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const nodemailer = require('nodemailer');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module.exports = class Email {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.config = config;
|
|
7
|
+
this.transporter = null;
|
|
8
|
+
this.init();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
init() {
|
|
12
|
+
const { email, password } = this.config;
|
|
13
|
+
this.transporter = nodemailer.createTransport({
|
|
14
|
+
service: 'qq',
|
|
15
|
+
auth: {
|
|
16
|
+
user: email,
|
|
17
|
+
pass: password,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async send({
|
|
23
|
+
to,
|
|
24
|
+
subject,
|
|
25
|
+
text = '',
|
|
26
|
+
html,
|
|
27
|
+
}) {
|
|
28
|
+
const { email } = this.config;
|
|
29
|
+
const mailOptions = {
|
|
30
|
+
from: email, // 发送者
|
|
31
|
+
to,
|
|
32
|
+
subject, // 标题
|
|
33
|
+
text, // 文本
|
|
34
|
+
html,
|
|
35
|
+
};
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
this.transporter.sendMail(mailOptions, (err, info) => {
|
|
38
|
+
if (err) {
|
|
39
|
+
return reject(err);
|
|
40
|
+
}
|
|
41
|
+
return resolve(info);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const axios = require('axios')
|
|
2
|
+
const { lodash } = require('multiple-quick-koa')
|
|
3
|
+
const send_url = 'http://wuliu.market.alicloudapi.com/kdi'
|
|
4
|
+
module.exports = class Singleton {
|
|
5
|
+
constructor (config) {
|
|
6
|
+
this.config = {
|
|
7
|
+
app_code: config.app_code,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 单例模式
|
|
12
|
+
*/
|
|
13
|
+
if (!Singleton.instance) {
|
|
14
|
+
Singleton.instance = this
|
|
15
|
+
}
|
|
16
|
+
const previous = Singleton.instance.getConfig()
|
|
17
|
+
if (!lodash.isEqual(previous, config)) {
|
|
18
|
+
Singleton.instance = this
|
|
19
|
+
}
|
|
20
|
+
return Singleton.instance
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async send ({ no }) {
|
|
24
|
+
const result = await axios({
|
|
25
|
+
method: 'GET',
|
|
26
|
+
url: `${send_url}?no=${no}`,
|
|
27
|
+
headers: {
|
|
28
|
+
Authorization: `APPCODE ${this.config.app_code}`,
|
|
29
|
+
},
|
|
30
|
+
}).then((res) => res.data)
|
|
31
|
+
return result.result
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getConfig () {
|
|
35
|
+
return this.config
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const axios = require('axios')
|
|
2
|
+
const util = require('util')
|
|
3
|
+
const { lodash } = require('multiple-quick-koa')
|
|
4
|
+
const toLocationUrl =
|
|
5
|
+
'https://apis.map.qq.com/ws/geocoder/v1/?location=%s&key=%s'
|
|
6
|
+
const toLngAndLatUrl =
|
|
7
|
+
'https://apis.map.qq.com/ws/geocoder/v1/?address=%s&key=%s'
|
|
8
|
+
module.exports = class Singleton {
|
|
9
|
+
constructor(key) {
|
|
10
|
+
this.key = key
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 单例模式
|
|
14
|
+
*/
|
|
15
|
+
if (!Singleton.instance) {
|
|
16
|
+
Singleton.instance = this
|
|
17
|
+
}
|
|
18
|
+
const previous = Singleton.instance.getConfig()
|
|
19
|
+
if (!lodash.isEqual(previous, key)) {
|
|
20
|
+
Singleton.instance = this
|
|
21
|
+
}
|
|
22
|
+
return Singleton.instance
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async direction({
|
|
26
|
+
from_latitude,
|
|
27
|
+
from_longitude,
|
|
28
|
+
to_latitude,
|
|
29
|
+
to_longitude,
|
|
30
|
+
name,
|
|
31
|
+
}) {
|
|
32
|
+
if (!from_latitude || !from_longitude || !to_latitude || !to_longitude) {
|
|
33
|
+
throw new Error('没输入起始位置')
|
|
34
|
+
}
|
|
35
|
+
if (!this.key) throw new Error('没有key')
|
|
36
|
+
const url = `https://apis.map.qq.com/ws/direction/v1/driving/?from=${from_latitude},${from_longitude}&to=${to_latitude},${to_longitude}&output=json&callback=cb&key=${this.key}`
|
|
37
|
+
const data = await axios.get(url).then((res) => res.data)
|
|
38
|
+
|
|
39
|
+
if (data.status === 0) return data.result
|
|
40
|
+
throw new Error(data.message)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async getToLoation({ longitude, latitude }) {
|
|
44
|
+
if (!longitude || !latitude) throw new Error('没输入地理位置')
|
|
45
|
+
if (!this.key) throw new Error('没有key')
|
|
46
|
+
const data = await axios
|
|
47
|
+
.get(util.format(toLocationUrl, `${latitude},${longitude}`, this.key))
|
|
48
|
+
.then((res) => res.data)
|
|
49
|
+
|
|
50
|
+
if (data.status === 0) return data.result
|
|
51
|
+
throw new Error(data.message)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async getToLngAndLat(name) {
|
|
55
|
+
if (!name) throw new Error('没输入地理名称')
|
|
56
|
+
if (!this.key) throw new Error('没有key')
|
|
57
|
+
const url = encodeURI(util.format(toLngAndLatUrl, `${name}`, this.key))
|
|
58
|
+
const data = await axios.get(url).then((res) => res.data)
|
|
59
|
+
|
|
60
|
+
if (data.status === 0) return data.result
|
|
61
|
+
if (data.message === '查询无结果') {
|
|
62
|
+
throw new Error(`找不到【${name}】,可能需要更详细一点(省市区)`)
|
|
63
|
+
} else {
|
|
64
|
+
throw new Error(data.message)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getConfig() {
|
|
69
|
+
return this.key
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const axios = require('axios')
|
|
2
|
+
const parseString = require('xml2js').parseString
|
|
3
|
+
|
|
4
|
+
const baseUrl = 'https://h5vv.video.qq.com/getinfo?'
|
|
5
|
+
|
|
6
|
+
const parseXML = (data) => {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
parseString(
|
|
9
|
+
data.data,
|
|
10
|
+
{
|
|
11
|
+
explicitArray: false,
|
|
12
|
+
},
|
|
13
|
+
function (err, result) {
|
|
14
|
+
if (err) reject(err)
|
|
15
|
+
resolve(result)
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const fetchVideo = (vid) => {
|
|
22
|
+
let params = {
|
|
23
|
+
otype: 'xml',
|
|
24
|
+
guid: 'b9a639401758a1a2b205bb1c41aaa01d',
|
|
25
|
+
platform: '11001',
|
|
26
|
+
host: 'm.v.qq.com',
|
|
27
|
+
sphttps: '1',
|
|
28
|
+
vid: vid,
|
|
29
|
+
}
|
|
30
|
+
let paramsArr = [].concat(baseUrl)
|
|
31
|
+
for (var key in params) {
|
|
32
|
+
paramsArr.push('' + key + '=' + params[key])
|
|
33
|
+
}
|
|
34
|
+
var url = paramsArr.join('&')
|
|
35
|
+
return axios.get(url)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const handlebaseVideo = (result) => {
|
|
39
|
+
let vl = result.root.vl
|
|
40
|
+
if (!vl) throw new Error('vid不合法或不存在')
|
|
41
|
+
let host = 'https://ugcbsy.qq.com/'
|
|
42
|
+
let filename = vl.vi.fn
|
|
43
|
+
let duration = Number(vl.vi.td)
|
|
44
|
+
let fvkey = vl.vi.fvkey
|
|
45
|
+
let name = vl.vi.ti
|
|
46
|
+
let vid = vl.vi.lnk
|
|
47
|
+
let video = `${host}${filename}?vkey=${fvkey}`
|
|
48
|
+
let image = `https://puui.qpic.cn/qqvideo_ori/0/${vid}_496_280/0`
|
|
49
|
+
// let img = `https://ypy.kuashou.org/tennis/qqvideo/${vid}.jpg`
|
|
50
|
+
return {
|
|
51
|
+
video,
|
|
52
|
+
image,
|
|
53
|
+
name,
|
|
54
|
+
vid,
|
|
55
|
+
duration,
|
|
56
|
+
from: 'qq',
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = async function (vid) {
|
|
61
|
+
let baseData = await fetchVideo(vid)
|
|
62
|
+
let baseResult = await parseXML(baseData)
|
|
63
|
+
return handlebaseVideo(baseResult)
|
|
64
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const util = require('util')
|
|
2
|
+
const axios = require('axios')
|
|
3
|
+
|
|
4
|
+
const { lodash } = require('multiple-quick-koa')
|
|
5
|
+
const getAccessTokenUrl =
|
|
6
|
+
'https://developer.toutiao.com/api/apps/token?grant_type=%s&appid=%s&secret=%s'
|
|
7
|
+
const createQRCodeUrl = 'https://developer.toutiao.com/api/apps/qrcode'
|
|
8
|
+
|
|
9
|
+
const fs = require('fs')
|
|
10
|
+
const LRU = require('lru-cache')
|
|
11
|
+
const cache = new LRU({
|
|
12
|
+
max: 100,
|
|
13
|
+
maxAge: 1000 * 60 * 60,
|
|
14
|
+
})
|
|
15
|
+
const uuid = require('node-uuid')
|
|
16
|
+
|
|
17
|
+
module.exports = class Singleton {
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = {
|
|
20
|
+
...config,
|
|
21
|
+
grant_type: 'client_credential',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 单例模式
|
|
26
|
+
*/
|
|
27
|
+
if (!Singleton.instance) {
|
|
28
|
+
Singleton.instance = this
|
|
29
|
+
}
|
|
30
|
+
const previous = Singleton.instance.getConfig()
|
|
31
|
+
if (!lodash.isEqual(previous, config)) {
|
|
32
|
+
Singleton.instance = this
|
|
33
|
+
}
|
|
34
|
+
return Singleton.instance
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
init() {
|
|
38
|
+
if (!this.config.appid || !this.config.secrect)
|
|
39
|
+
throw new Error('没有配置appid或secrect')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async getAccessToken() {
|
|
43
|
+
const { appid, secrect, grant_type } = this.config
|
|
44
|
+
if (cache.get(appid)) {
|
|
45
|
+
return cache.get(appid)
|
|
46
|
+
}
|
|
47
|
+
const url = util.format(getAccessTokenUrl, grant_type, appid, secrect)
|
|
48
|
+
const { access_token } = await axios.get(url).then((res) => res.data)
|
|
49
|
+
cache.set(appid, access_token)
|
|
50
|
+
return access_token
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async createQR(options) {
|
|
54
|
+
if (!this.config.targetPath) throw new Error('没有配置文件夹')
|
|
55
|
+
|
|
56
|
+
const isExists = fs.existsSync(
|
|
57
|
+
`${this.config.targetPath}/${options.filename}.png`
|
|
58
|
+
)
|
|
59
|
+
if (isExists) return `${options.filename}.png`
|
|
60
|
+
|
|
61
|
+
const access_token = await this.getAccessToken()
|
|
62
|
+
const payLoad = {
|
|
63
|
+
appname: 'douyin',
|
|
64
|
+
filename: '',
|
|
65
|
+
access_token,
|
|
66
|
+
...options,
|
|
67
|
+
}
|
|
68
|
+
const creatuuid = payLoad.filename ? payLoad.filename : uuid.v1()
|
|
69
|
+
|
|
70
|
+
const bufferResult = await axios
|
|
71
|
+
.post(createQRCodeUrl, payLoad, {
|
|
72
|
+
headers: {
|
|
73
|
+
'content-type': 'application/json',
|
|
74
|
+
},
|
|
75
|
+
responseType: 'arraybuffer',
|
|
76
|
+
})
|
|
77
|
+
.then((res) => {
|
|
78
|
+
if (res.headers['content-type'].includes('json')) {
|
|
79
|
+
return JSON.parse(Buffer.from(res.data).toString('utf8'))
|
|
80
|
+
}
|
|
81
|
+
return res.data
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
if (bufferResult.errcode) {
|
|
85
|
+
if (bufferResult.errcode === 40001) {
|
|
86
|
+
cache.reset()
|
|
87
|
+
return await this.createQR(options)
|
|
88
|
+
}
|
|
89
|
+
throw new Error(bufferResult.errmsg)
|
|
90
|
+
}
|
|
91
|
+
await fs.writeFileSync(
|
|
92
|
+
`${this.config.targetPath}/${creatuuid}.png`,
|
|
93
|
+
bufferResult
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
return `${creatuuid}.png`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
getConfig() {
|
|
100
|
+
return this.config
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const util = require('util')
|
|
2
|
+
const axios = require('axios')
|
|
3
|
+
const getAccessTokenUrl = `https://api.weixin.qq.com/cgi-bin/token?grant_type=%s&appid=%s&secret=%s`
|
|
4
|
+
const getTicketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi'
|
|
5
|
+
const sha1 = require('sha1')
|
|
6
|
+
const LRU = require('lru-cache')
|
|
7
|
+
const cache = new LRU({
|
|
8
|
+
max: 100,
|
|
9
|
+
maxAge: 1000 * 60 * 60
|
|
10
|
+
})
|
|
11
|
+
const {
|
|
12
|
+
lodash
|
|
13
|
+
} = require('multiple-quick-koa')
|
|
14
|
+
|
|
15
|
+
module.exports = class Singleton {
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = {
|
|
18
|
+
...config,
|
|
19
|
+
|
|
20
|
+
noncestr: 'kuashou',
|
|
21
|
+
grant_type: 'client_credential',
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 单例模式
|
|
25
|
+
*/
|
|
26
|
+
if (!Singleton.instance) {
|
|
27
|
+
Singleton.instance = this
|
|
28
|
+
}
|
|
29
|
+
const previous = Singleton.instance.getConfig()
|
|
30
|
+
if (!lodash.isEqual(previous, config)) {
|
|
31
|
+
Singleton.instance = this
|
|
32
|
+
}
|
|
33
|
+
return Singleton.instance
|
|
34
|
+
}
|
|
35
|
+
init() {
|
|
36
|
+
if (!this.config.appid || !this.config.secrect) throw new Error('没有配置appid或secrect')
|
|
37
|
+
}
|
|
38
|
+
async getAccessToken() {
|
|
39
|
+
const { appid, secrect, grant_type } = this.config
|
|
40
|
+
if (cache.get('access_token')) {
|
|
41
|
+
return cache.get('access_token')
|
|
42
|
+
}
|
|
43
|
+
const url = util.format(getAccessTokenUrl, grant_type, appid, secrect)
|
|
44
|
+
const result = await axios.get(url).then(res => res.data)
|
|
45
|
+
if (result.errcode) throw new Error(result.errmsg)
|
|
46
|
+
|
|
47
|
+
cache.set('access_token', result.access_token)
|
|
48
|
+
return result.access_token
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async getTicket() {
|
|
52
|
+
const access_token = await this.getAccessToken()
|
|
53
|
+
const url = util.format(getTicketUrl, access_token)
|
|
54
|
+
const result = await axios.get(url).then(res => res.data)
|
|
55
|
+
if (result.errcode) throw new Error(result.errmsg)
|
|
56
|
+
|
|
57
|
+
cache.set('ticket', result.ticket)
|
|
58
|
+
return result.ticket
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async sign(url) {
|
|
62
|
+
const jsapi_ticket = await this.getTicket()
|
|
63
|
+
const noncestr = this.config.noncestr
|
|
64
|
+
const timestamp = Math.floor(Date.now() / 1000)
|
|
65
|
+
|
|
66
|
+
const result = {
|
|
67
|
+
noncestr,
|
|
68
|
+
timestamp,
|
|
69
|
+
url,
|
|
70
|
+
jsapi_ticket,
|
|
71
|
+
signature: sha1('jsapi_ticket=' + jsapi_ticket + '&noncestr=' + noncestr + '×tamp=' + timestamp + '&url=' + url)
|
|
72
|
+
}
|
|
73
|
+
return result
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getConfig () {
|
|
77
|
+
return this.config
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const cheerio = require('cheerio')
|
|
2
|
+
const moment = require('moment')
|
|
3
|
+
|
|
4
|
+
exports.handleHtml = async function (html) {
|
|
5
|
+
const $ = cheerio.load(html, {
|
|
6
|
+
decodeEntities: false,
|
|
7
|
+
})
|
|
8
|
+
if ($('body').attr('class').indexOf('page_share_img') > -1) {
|
|
9
|
+
console.log('idjd')
|
|
10
|
+
const imgs = $('#img_list').html()
|
|
11
|
+
const content = html
|
|
12
|
+
.split("document.getElementById('js_image_desc').innerHTML = \"")[1]
|
|
13
|
+
.split('".replace')[0]
|
|
14
|
+
return {
|
|
15
|
+
// publish_time: $('#publish_time').text().trim(),
|
|
16
|
+
desc: '',
|
|
17
|
+
html: `<div>${content}</div><div>${imgs}</div>`,
|
|
18
|
+
title: content,
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const ct = html.split('var ct = "')[1].split('";')[0]
|
|
22
|
+
const author = html.split('var nickname = "')[1].split('";')[0]
|
|
23
|
+
const desc = html.split('var msg_desc = htmlDecode("')[1].split('");')[0]
|
|
24
|
+
const title = html.split("var msg_title = '")[1].split("'.html(false)")[0]
|
|
25
|
+
const image = html.split('var msg_cdn_url = "')[1].split('";')[0]
|
|
26
|
+
const body = $('#js_content')
|
|
27
|
+
// var videos = body.find('iframe')
|
|
28
|
+
const imgs = body.find('img')
|
|
29
|
+
imgs.each(function (item) {
|
|
30
|
+
var src = $(this).attr('data-src').split('?')[0]
|
|
31
|
+
$(this).attr('src', src)
|
|
32
|
+
})
|
|
33
|
+
const asyncTasks = []
|
|
34
|
+
html = body
|
|
35
|
+
.html()
|
|
36
|
+
.replace(/\s{2,}/g, '')
|
|
37
|
+
.replace(/\\<热卖单品\\>/g, '热卖单品')
|
|
38
|
+
.replace(/url\(\\"/g, "url(\\'")
|
|
39
|
+
.replace(/\\"\)/g, "\\')")
|
|
40
|
+
// html = deal(html)
|
|
41
|
+
// html = html.replace('url("', 'url(\'')
|
|
42
|
+
// html = html.replace('")', '\')')
|
|
43
|
+
const publish_time = moment(parseInt(ct + '000'))
|
|
44
|
+
return {
|
|
45
|
+
asyncTasks,
|
|
46
|
+
image,
|
|
47
|
+
author,
|
|
48
|
+
publish_time,
|
|
49
|
+
desc,
|
|
50
|
+
html,
|
|
51
|
+
title,
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
var crypto = require('crypto')
|
|
2
|
+
|
|
3
|
+
function WXBizDataCrypt(appId, sessionKey) {
|
|
4
|
+
this.appId = appId
|
|
5
|
+
this.sessionKey = sessionKey
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
|
|
9
|
+
// base64 decode
|
|
10
|
+
var sessionKey = Buffer.from(this.sessionKey, 'base64')
|
|
11
|
+
encryptedData = Buffer.from(encryptedData, 'base64')
|
|
12
|
+
iv = Buffer.from(iv, 'base64')
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
// 解密
|
|
16
|
+
var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
|
|
17
|
+
// 设置自动 padding 为 true,删除填充补位
|
|
18
|
+
decipher.setAutoPadding(true)
|
|
19
|
+
var decoded = decipher.update(encryptedData, 'binary', 'utf8')
|
|
20
|
+
decoded += decipher.final('utf8')
|
|
21
|
+
|
|
22
|
+
decoded = JSON.parse(decoded)
|
|
23
|
+
|
|
24
|
+
return decoded
|
|
25
|
+
} catch (err) {
|
|
26
|
+
throw new Error('系统开小差了,请重试')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (decoded.watermark.appid !== this.appId) {
|
|
30
|
+
throw new Error('Illegal Buffer')
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = WXBizDataCrypt
|