twikoo-vercel 1.4.3 → 1.4.7
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/api/index.js +83 -19
- package/package.json +1 -1
package/api/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Twikoo vercel function v1.4.
|
|
2
|
+
* Twikoo vercel function v1.4.7
|
|
3
3
|
* (c) 2020-present iMaeGoo
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -27,7 +27,7 @@ const window = new JSDOM('').window
|
|
|
27
27
|
const DOMPurify = createDOMPurify(window)
|
|
28
28
|
|
|
29
29
|
// 常量 / constants
|
|
30
|
-
const VERSION = '1.4.
|
|
30
|
+
const VERSION = '1.4.7'
|
|
31
31
|
const RES_CODE = {
|
|
32
32
|
SUCCESS: 0,
|
|
33
33
|
NO_PARAM: 100,
|
|
@@ -123,6 +123,9 @@ module.exports = async (requestArg, responseArg) => {
|
|
|
123
123
|
case 'GET_RECENT_COMMENTS': // >= 0.2.7
|
|
124
124
|
res = await getRecentComments(event)
|
|
125
125
|
break
|
|
126
|
+
case 'EMAIL_TEST': // >= 1.4.6
|
|
127
|
+
res = await emailTest(event)
|
|
128
|
+
break
|
|
126
129
|
default:
|
|
127
130
|
if (event.event) {
|
|
128
131
|
res.code = RES_CODE.EVENT_NOT_EXIST
|
|
@@ -177,6 +180,7 @@ async function connectToDatabase (uri) {
|
|
|
177
180
|
if (db) return db
|
|
178
181
|
if (!uri) throw new Error('未设置环境变量 MONGODB_URI')
|
|
179
182
|
// If no connection is cached, create a new one
|
|
183
|
+
console.log('Connecting to database...')
|
|
180
184
|
const client = await MongoClient.connect(uri, {
|
|
181
185
|
useNewUrlParser: true,
|
|
182
186
|
useUnifiedTopology: true
|
|
@@ -185,6 +189,7 @@ async function connectToDatabase (uri) {
|
|
|
185
189
|
// using the database path of the connection string
|
|
186
190
|
db = await client.db((new URL(uri)).pathname.substr(1))
|
|
187
191
|
// Cache the database connection and return the connection
|
|
192
|
+
console.log('Connected to database')
|
|
188
193
|
return db
|
|
189
194
|
}
|
|
190
195
|
|
|
@@ -577,13 +582,19 @@ function jsonParse (content) {
|
|
|
577
582
|
|
|
578
583
|
// Valine 导入
|
|
579
584
|
async function commentImportValine (valineDb, log) {
|
|
580
|
-
|
|
585
|
+
let arr
|
|
586
|
+
if (valineDb instanceof Array) {
|
|
587
|
+
arr = valineDb
|
|
588
|
+
} else if (valineDb && valineDb.results) {
|
|
589
|
+
arr = valineDb.results
|
|
590
|
+
}
|
|
591
|
+
if (!arr) {
|
|
581
592
|
log('Valine 评论文件格式有误')
|
|
582
593
|
return
|
|
583
594
|
}
|
|
584
595
|
const comments = []
|
|
585
|
-
log(`共 ${
|
|
586
|
-
for (const comment of
|
|
596
|
+
log(`共 ${arr.length} 条评论`)
|
|
597
|
+
for (const comment of arr) {
|
|
587
598
|
try {
|
|
588
599
|
const parsed = {
|
|
589
600
|
_id: comment.objectId,
|
|
@@ -835,12 +846,19 @@ async function commentSubmit (event) {
|
|
|
835
846
|
res.id = comment.id
|
|
836
847
|
// 异步垃圾检测、发送评论通知
|
|
837
848
|
try {
|
|
838
|
-
await axios.post(`${request.headers['x-forwarded-proto']}://${request.headers.host}`, {
|
|
839
|
-
event: 'POST_SUBMIT',
|
|
840
|
-
comment
|
|
841
|
-
}, { headers: { 'x-twikoo-recursion': 'true' }, timeout: 300 }) // 设置较短的 timeout 来实现异步
|
|
842
|
-
} catch (e) {
|
|
843
849
|
console.log('开始异步垃圾检测、发送评论通知')
|
|
850
|
+
console.time('POST_SUBMIT')
|
|
851
|
+
await Promise.race([
|
|
852
|
+
axios.post(`https://${process.env.VERCEL_URL}`, {
|
|
853
|
+
event: 'POST_SUBMIT',
|
|
854
|
+
comment
|
|
855
|
+
}, { headers: { 'x-twikoo-recursion': 'true' } }),
|
|
856
|
+
// 如果超过 5 秒还没收到异步返回,直接继续,减少用户等待的时间
|
|
857
|
+
new Promise((resolve) => setTimeout(resolve, 5000))
|
|
858
|
+
])
|
|
859
|
+
console.timeEnd('POST_SUBMIT')
|
|
860
|
+
} catch (e) {
|
|
861
|
+
console.log('POST_SUBMIT 失败', e)
|
|
844
862
|
}
|
|
845
863
|
return res
|
|
846
864
|
}
|
|
@@ -872,13 +890,14 @@ async function sendNotice (comment) {
|
|
|
872
890
|
noticeReply(comment),
|
|
873
891
|
noticeWeChat(comment),
|
|
874
892
|
noticePushPlus(comment),
|
|
893
|
+
noticeWeComPush(comment),
|
|
875
894
|
noticeQQ(comment)
|
|
876
895
|
]).catch(console.error)
|
|
877
896
|
return { code: RES_CODE.SUCCESS }
|
|
878
897
|
}
|
|
879
898
|
|
|
880
899
|
// 初始化邮件插件
|
|
881
|
-
async function initMailer () {
|
|
900
|
+
async function initMailer ({ throwErr = false } = {}) {
|
|
882
901
|
try {
|
|
883
902
|
if (!config || !config.SMTP_USER || !config.SMTP_PASS) {
|
|
884
903
|
throw new Error('数据库配置不存在')
|
|
@@ -899,13 +918,16 @@ async function initMailer () {
|
|
|
899
918
|
throw new Error('SMTP 服务器没有配置')
|
|
900
919
|
}
|
|
901
920
|
transporter = nodemailer.createTransport(transportConfig)
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
})
|
|
921
|
+
try {
|
|
922
|
+
const success = await transporter.verify()
|
|
923
|
+
if (success) console.log('SMTP 邮箱配置正常')
|
|
924
|
+
} catch (error) {
|
|
925
|
+
throw new Error('SMTP 邮箱配置异常:', error)
|
|
926
|
+
}
|
|
906
927
|
return true
|
|
907
928
|
} catch (e) {
|
|
908
929
|
console.error('邮件初始化异常:', e.message)
|
|
930
|
+
if (throwErr) throw e
|
|
909
931
|
return false
|
|
910
932
|
}
|
|
911
933
|
}
|
|
@@ -917,7 +939,8 @@ async function noticeMaster (comment) {
|
|
|
917
939
|
const IM_PUSH_CONFIGS = [
|
|
918
940
|
'SC_SENDKEY',
|
|
919
941
|
'QM_SENDKEY',
|
|
920
|
-
'PUSH_PLUS_TOKEN'
|
|
942
|
+
'PUSH_PLUS_TOKEN',
|
|
943
|
+
'WECOM_API_URL'
|
|
921
944
|
]
|
|
922
945
|
// 判断是否存在即时消息推送配置
|
|
923
946
|
const hasIMPushConfig = IM_PUSH_CONFIGS.some(item => !!config[item])
|
|
@@ -1008,6 +1031,21 @@ async function noticePushPlus (comment) {
|
|
|
1008
1031
|
console.log('pushplus 通知结果:', sendResult)
|
|
1009
1032
|
}
|
|
1010
1033
|
|
|
1034
|
+
// 自定义WeCom企业微信api通知
|
|
1035
|
+
async function noticeWeComPush (comment) {
|
|
1036
|
+
if (!config.WECOM_API_URL) {
|
|
1037
|
+
console.log('未配置 WECOM_API_URL,跳过企业微信推送')
|
|
1038
|
+
return
|
|
1039
|
+
}
|
|
1040
|
+
if (config.BLOGGER_EMAIL === comment.mail) return
|
|
1041
|
+
const SITE_URL = config.SITE_URL
|
|
1042
|
+
const WeComContent = config.SITE_NAME + '有新评论啦!🎉🎉' + '\n\n' + '@' + comment.nick + '说:' + $(comment.comment).text() + '\n' + 'E-mail: ' + comment.mail + '\n' + 'IP: ' + comment.ip + '\n' + '点此查看完整内容:' + appendHashToUrl(comment.href || SITE_URL + comment.url, comment.id)
|
|
1043
|
+
const WeComApiContent = encodeURIComponent(WeComContent)
|
|
1044
|
+
const WeComApiUrl = config.WECOM_API_URL
|
|
1045
|
+
const sendResult = await axios.get(WeComApiUrl + WeComApiContent)
|
|
1046
|
+
console.log('WinxinPush 通知结果:', sendResult)
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1011
1049
|
// QQ通知
|
|
1012
1050
|
async function noticeQQ (comment) {
|
|
1013
1051
|
if (!config.QM_SENDKEY) {
|
|
@@ -1047,12 +1085,13 @@ function getIMPushContent (comment) {
|
|
|
1047
1085
|
async function noticeReply (currentComment) {
|
|
1048
1086
|
if (!currentComment.pid) return
|
|
1049
1087
|
if (!transporter) if (!await initMailer()) return
|
|
1050
|
-
|
|
1088
|
+
const parentComment = await db
|
|
1051
1089
|
.collection('comment')
|
|
1052
1090
|
.findOne({ _id: currentComment.pid })
|
|
1053
|
-
parentComment = parentComment.data[0]
|
|
1054
1091
|
// 回复给博主,因为会发博主通知邮件,所以不再重复通知
|
|
1055
1092
|
if (config.BLOGGER_EMAIL === parentComment.mail) return
|
|
1093
|
+
// 回复自己的评论,不邮件通知
|
|
1094
|
+
if (currentComment.mail === parentComment.mail) return
|
|
1056
1095
|
const PARENT_NICK = parentComment.nick
|
|
1057
1096
|
const SITE_NAME = config.SITE_NAME
|
|
1058
1097
|
const NICK = currentComment.nick
|
|
@@ -1116,7 +1155,7 @@ function appendHashToUrl (url, hash) {
|
|
|
1116
1155
|
async function parse (comment) {
|
|
1117
1156
|
const timestamp = Date.now()
|
|
1118
1157
|
const isAdminUser = await isAdmin()
|
|
1119
|
-
const isBloggerMail = comment.mail === config.BLOGGER_EMAIL
|
|
1158
|
+
const isBloggerMail = comment.mail && comment.mail === config.BLOGGER_EMAIL
|
|
1120
1159
|
if (isBloggerMail && !isAdminUser) throw new Error('请先登录管理面板,再使用博主身份发送评论')
|
|
1121
1160
|
const commentDo = {
|
|
1122
1161
|
_id: uuidv4().replace(/-/g, ''),
|
|
@@ -1390,6 +1429,31 @@ async function getRecentComments (event) {
|
|
|
1390
1429
|
return res
|
|
1391
1430
|
}
|
|
1392
1431
|
|
|
1432
|
+
async function emailTest (event) {
|
|
1433
|
+
const res = {}
|
|
1434
|
+
const isAdminUser = await isAdmin()
|
|
1435
|
+
if (isAdminUser) {
|
|
1436
|
+
try {
|
|
1437
|
+
if (!transporter) {
|
|
1438
|
+
await initMailer({ throwErr: true })
|
|
1439
|
+
}
|
|
1440
|
+
const sendResult = await transporter.sendMail({
|
|
1441
|
+
from: config.SENDER_EMAIL,
|
|
1442
|
+
to: event.mail || config.BLOGGER_EMAIL || config.SENDER_EMAIL,
|
|
1443
|
+
subject: 'Twikoo 邮件通知测试邮件',
|
|
1444
|
+
html: '如果您收到这封邮件,说明 Twikoo 邮件功能配置正确'
|
|
1445
|
+
})
|
|
1446
|
+
res.result = sendResult
|
|
1447
|
+
} catch (e) {
|
|
1448
|
+
res.message = e.message
|
|
1449
|
+
}
|
|
1450
|
+
} else {
|
|
1451
|
+
res.code = RES_CODE.NEED_LOGIN
|
|
1452
|
+
res.message = '请先登录'
|
|
1453
|
+
}
|
|
1454
|
+
return res
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1393
1457
|
function getAvatar (comment) {
|
|
1394
1458
|
if (comment.avatar) {
|
|
1395
1459
|
return comment.avatar
|
package/package.json
CHANGED