diff --git a/README.md b/README.md index 7f473c542..b8fda00f2 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,9 @@ SENDER_EMAIL | xxxxxx@qq.com | [必填]发件邮箱 ADMIN_URL | https://xxx.leanapp.cn/ | [建议]Web主机二级域名,用于自动唤醒 BLOGGER_EMAIL | xxxxx@gmail.com | [可选]博主通知收件地址,默认使用SENDER_EMAIL AKISMET_KEY | xxxxxxxxxxxx | [可选]Akismet Key 用于垃圾评论检测,设为MANUAL_REVIEW开启人工审核,留空不使用反垃圾 - +BAIDU_APPID | xxxxxxxxxxxx | [可选]百度云内容审核引擎APPID(用于垃圾评论检测,设为MANUAL_REVIEW开启人工审核,优先级高于AKISMET_KEY,若配置则优先使用Baidu内容审核) +BAIDU_APIKEY | xxxxxxxxxxxx | [可选]若启用百度内容审核则必填,可前往https://ai.baidu.com/censoring 配置审核策略和申请应用AK SK +BAIDU_SECRET | xxxxxxxxxxxx | [可选]若启用百度内容审核则必填 **以上必填参数请务必正确设置。** @@ -148,6 +150,27 @@ COMMENT | 新评论内容 --- | ------ | ------ AKISMET_KEY | xxxxxxxxxxxx | [可选]Akismet Key 用于垃圾评论检测 +## 百度AI垃圾评论检测 + +> 使用百度内容审核平台替代Akismet的审核功能,白名单和黑名单的提交功能由于百度没有开放接口所以只能在百度后台进行配置。 +> 相比于Akismet,百度内容审核平台属于付费产品,但个人有一定免费额度(文本接口实名认证后累计50万次调用,还有图像接口,详见[计费规则](https://ai.baidu.com/ai-doc/ANTIPORN/lk3h6x7if)) +> 百度审核只审核评论的内容,不需要任何用户信息,相比Akismet来说更加简单直接。同时支持配置[自定义审核策略](https://ai.baidu.com/censoring),可对色情、暴恐、政治敏感、恶意推广、低俗辱骂、低质灌水等内容进行阈值自定义调整,使用上更加灵活方便。 +> 同时由于百度没有提供黑白名单的API接口(通过配置策略自主上传),所以如果选择了百度审核,则本管理后台的黑白名单的功能将不会生效,请前往百度后台自主配置。 + +如果还没有百度云账号,你可以去百度大脑的 [AI开放平台](https://ai.baidu.com/tech/textcensoring) 免费申请一个; + +**当BAIDU_APPID设为MANUAL_REVIEW时,开启人工审核模式;** +如果你不需要反垃圾评论,BAIDU_APPID环境变量可以忽略。 + +~~**为了实现较为精准的垃圾评论识别,采集的判据除了评论内容、邮件地址和网站地址外,还包括评论者的IP地址、浏览器信息等,但仅在云引擎后台使用这些数据,确保隐私和安全。**~~ +百度审核不需要这些内容 + +环境变量 | 示例 | 说明 +--- | ------ | ------ +BAIDU_APPID | xxxxxxxxxxxx | [可选]百度云内容审核引擎APPID(用于垃圾评论检测,设为MANUAL_REVIEW开启人工审核,优先级高于AKISMET_KEY,若配置则优先使用Baidu内容审核) +BAIDU_APIKEY | xxxxxxxxxxxx | [可选]若启用百度内容审核则必填,可前往https://ai.baidu.com/censoring 配置审核策略和申请应用AK SK +BAIDU_SECRET | xxxxxxxxxxxx | [可选]若启用百度内容审核则必填 + ## 防止云引擎休眠 关于自动休眠的官方说法:[点击查看](https://leancloud.cn/docs/leanengine_plan.html#hash633315134) diff --git a/cloud.js b/cloud.js index bd9173c11..b858a84b5 100644 --- a/cloud.js +++ b/cloud.js @@ -4,7 +4,7 @@ const Comment = AV.Object.extend('Comment'); const request = require('request'); const spam = require('./utilities/check-spam'); -function sendNotification(currentComment, defaultIp) { +async function sendNotification(currentComment, defaultIp) { // 发送博主通知邮件 if (currentComment.get('mail') !== process.env.BLOGGER_EMAIL) { mail.notice(currentComment); @@ -12,10 +12,10 @@ function sendNotification(currentComment, defaultIp) { let ip = currentComment.get('ip') || defaultIp; console.log('IP: %s', ip); - spam.checkSpam(currentComment, ip); + await spam.checkSpam(currentComment, ip); // AT评论通知 - let rid =currentComment.get('pid') || currentComment.get('rid'); + let rid = currentComment.get('pid') || currentComment.get('rid'); if (!rid) { console.log("这条评论没有 @ 任何人"); @@ -26,16 +26,14 @@ function sendNotification(currentComment, defaultIp) { } let query = new AV.Query('Comment'); - query.get(rid).then(function (parentComment) { - if (parentComment.get('mail') && parentComment.get('mail') !== process.env.BLOGGER_EMAIL) { - mail.send(currentComment, parentComment); - } else { - console.log('被@者匿名,不会发送通知'); - } - - }, function (error) { - console.warn('获取@对象失败!'); + let parentComment = await query.get(rid).catch(err => { + return console.warn('获取@对象失败!'); }); + if (parentComment.get('mail') && parentComment.get('mail') !== process.env.BLOGGER_EMAIL) { + mail.send(currentComment, parentComment); + } else { + console.log('被@者匿名,不会发送通知'); + } } AV.Cloud.afterSave('Comment', function (req) { @@ -44,30 +42,29 @@ AV.Cloud.afterSave('Comment', function (req) { return sendNotification(currentComment, req.meta.remoteAddress); }); -AV.Cloud.define('resend_mails', function(req) { +AV.Cloud.define('resend_mails', function (req) { let query = new AV.Query(Comment); - query.greaterThanOrEqualTo('createdAt', new Date(new Date().getTime() - 24*60*60*1000)); + query.greaterThanOrEqualTo('createdAt', new Date(new Date().getTime() - 24 * 60 * 60 * 1000)); query.notEqualTo('isNotified', true); // 如果你的评论量很大,可以适当调高数量限制,最高1000 query.limit(200); - return query.find().then(function(results) { - new Promise((resolve, reject)=>{ + return query.find().then(function (results) { + new Promise((resolve, reject) => { count = results.length; - for (var i = 0; i < results.length; i++ ) { + for (var i = 0; i < results.length; i++) { sendNotification(results[i], req.meta.remoteAddress); } resolve(count); - }).then((count)=>{ + }).then((count) => { console.log(`昨日${count}条未成功发送的通知邮件处理完毕!`); - }).catch(()=>{ + }).catch(() => { }); }); - }); +}); -AV.Cloud.define('self_wake', function(req) { +AV.Cloud.define('self_wake', function (req) { request(process.env.ADMIN_URL, function (error, response, body) { console.log('自唤醒任务执行成功,响应状态码为:', response && response.statusCode); - }); -}); - + }); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 278be89af..ba5a9d207 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,27 @@ "dev": true }, "accepts": { - "version": "1.2.13", - "resolved": "http://registry.npm.taobao.org/accepts/download/accepts-1.2.13.tgz", - "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "requires": { - "mime-types": "~2.1.6", - "negotiator": "0.5.3" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "dependencies": { + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + } } }, "ajv": { @@ -134,6 +149,11 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, "array-unique": { "version": "0.3.2", "resolved": "http://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz", @@ -201,12 +221,40 @@ "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8=" }, "axios": { - "version": "0.18.0", - "resolved": "http://registry.npm.taobao.org/axios/download/axios-0.18.0.tgz", - "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", "requires": { - "follow-redirects": "^1.3.0", - "is-buffer": "^1.1.5" + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, "babel-runtime": { @@ -218,6 +266,34 @@ "regenerator-runtime": "^0.11.0" } }, + "baidu-aip-sdk": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/baidu-aip-sdk/-/baidu-aip-sdk-2.4.5.tgz", + "integrity": "sha512-0OwuqOJsOhyGodInFZ3v7WIZ4plBhZjLhvUJ7aAKmuOlEUWLdWXQXCxSTIlPNgKmSkkvHpdbctyL/kWDXceNew==", + "requires": { + "debug": "^2.6.0", + "iconv-lite": "^0.4.15", + "keep-alive-agent": "0.0.1", + "request": "^2.79.0", + "should": "^13.2.0", + "underscore": "^1.8.3" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "balanced-match": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", @@ -303,38 +379,78 @@ "integrity": "sha1-fQHG+WFsmlGrD4xUmnnf5uwz76c=" }, "body-parser": { - "version": "1.12.3", - "resolved": "http://registry.npm.taobao.org/body-parser/download/body-parser-1.12.3.tgz", - "integrity": "sha1-X0C/F+eCO+aJXU01WCdS42z5f3E=", - "requires": { - "bytes": "1.0.0", - "content-type": "~1.0.1", - "debug": "~2.1.3", - "depd": "~1.0.1", - "iconv-lite": "0.4.8", - "on-finished": "~2.2.0", - "qs": "2.4.1", - "raw-body": "1.3.4", - "type-is": "~1.6.1" + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" }, "dependencies": { "debug": { - "version": "2.1.3", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.1.3.tgz", - "integrity": "sha1-zoqxte6PvuK/o7Yzyrk9NmtjQY4=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "ms": "0.7.0" + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" } }, "ms": { - "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.0.tgz", - "integrity": "sha1-hlvpTC5zl62KV9pqYzpuLzB5i4M=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "qs": { - "version": "2.4.1", - "resolved": "http://registry.npm.taobao.org/qs/download/qs-2.4.1.tgz", - "integrity": "sha1-aMuuqXEBNCaoDBQE+taxprEXUkU=" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } } } }, @@ -439,9 +555,9 @@ } }, "bytes": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/bytes/download/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "cache-base": { "version": "1.0.1", @@ -724,9 +840,12 @@ } }, "content-disposition": { - "version": "0.5.0", - "resolved": "http://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.0.tgz", - "integrity": "sha1-QoT+auBjCHRjnkToCkGMKTQTXp4=" + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } }, "content-type": { "version": "1.0.4", @@ -789,11 +908,6 @@ "resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "crc": { - "version": "3.2.1", - "resolved": "http://registry.npm.taobao.org/crc/download/crc-3.2.1.tgz", - "integrity": "sha1-XZyPt3okXNXsopHl0tAFM0urAII=" - }, "create-error-class": { "version": "3.0.2", "resolved": "http://registry.npm.taobao.org/create-error-class/download/create-error-class-3.0.2.tgz", @@ -905,14 +1019,14 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "depd": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/depd/download/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "destroy": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/destroy/download/destroy-1.0.3.tgz", - "integrity": "sha1-tDO0ck5x/YVR2YhRdIUcX8N34sk=" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "dot-prop": { "version": "4.2.0", @@ -939,9 +1053,9 @@ } }, "ee-first": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/ee-first/download/ee-first-1.1.0.tgz", - "integrity": "sha1-ag18YiHkkP7v2S7D9EHJzozQl/Q=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "ejs": { "version": "2.3.1", @@ -959,9 +1073,9 @@ "integrity": "sha1-KUVLjbIbc/vvHfBww13Am3/WBsQ=" }, "escape-html": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.1.tgz", - "integrity": "sha1-GBoobq05ejmpKFfPsdQwUuNWv/A=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", @@ -970,12 +1084,9 @@ "dev": true }, "etag": { - "version": "1.5.1", - "resolved": "http://registry.npm.taobao.org/etag/download/etag-1.5.1.tgz", - "integrity": "sha1-VMUN4E7kJpVWKSWsVmWIKRvn6eo=", - "requires": { - "crc": "3.2.1" - } + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "eventemitter3": { "version": "2.0.3", @@ -1048,58 +1159,96 @@ } }, "express": { - "version": "4.12.3", - "resolved": "http://registry.npm.taobao.org/express/download/express-4.12.3.tgz", - "integrity": "sha1-a52UrsWuAycNhtOQwneoxaWtDuI=", - "requires": { - "accepts": "~1.2.5", - "content-disposition": "0.5.0", - "content-type": "~1.0.1", - "cookie": "0.1.2", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", "cookie-signature": "1.0.6", - "debug": "~2.1.3", - "depd": "~1.0.0", - "escape-html": "1.0.1", - "etag": "~1.5.1", - "finalhandler": "0.3.4", - "fresh": "0.2.4", - "merge-descriptors": "1.0.0", - "methods": "~1.1.1", - "on-finished": "~2.2.0", - "parseurl": "~1.3.0", - "path-to-regexp": "0.1.3", - "proxy-addr": "~1.0.7", - "qs": "2.4.1", - "range-parser": "~1.0.2", - "send": "0.12.2", - "serve-static": "~1.9.2", - "type-is": "~1.6.1", - "utils-merge": "1.0.0", - "vary": "~1.0.0" + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "dependencies": { "cookie": { - "version": "0.1.2", - "resolved": "http://registry.npm.taobao.org/cookie/download/cookie-0.1.2.tgz", - "integrity": "sha1-cv7D0k5Io0Mgc9kMEmQgBQYQBLE=" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, "debug": { - "version": "2.1.3", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.1.3.tgz", - "integrity": "sha1-zoqxte6PvuK/o7Yzyrk9NmtjQY4=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "requires": { - "ms": "0.7.0" + "mime-db": "1.43.0" } }, "ms": { - "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.0.tgz", - "integrity": "sha1-hlvpTC5zl62KV9pqYzpuLzB5i4M=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, "qs": { - "version": "2.4.1", - "resolved": "http://registry.npm.taobao.org/qs/download/qs-2.4.1.tgz", - "integrity": "sha1-aMuuqXEBNCaoDBQE+taxprEXUkU=" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } } } }, @@ -1233,50 +1382,36 @@ } }, "finalhandler": { - "version": "0.3.4", - "resolved": "http://registry.npm.taobao.org/finalhandler/download/finalhandler-0.3.4.tgz", - "integrity": "sha1-R4fTVz0HmuiwdTbyawuRHrryoqw=", - "requires": { - "debug": "~2.1.3", - "escape-html": "1.0.1", - "on-finished": "~2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.1.3", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.1.3.tgz", - "integrity": "sha1-zoqxte6PvuK/o7Yzyrk9NmtjQY4=", - "requires": { - "ms": "0.7.0" - } - }, - "ms": { - "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.0.tgz", - "integrity": "sha1-hlvpTC5zl62KV9pqYzpuLzB5i4M=" - } - } - }, - "follow-redirects": { - "version": "1.6.1", - "resolved": "http://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.6.1.tgz", - "integrity": "sha1-UUlzxEtXVzaLrYvd/lL4HwFclMs=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "requires": { - "debug": "=3.1.0" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } }, "ms": { "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" } } }, @@ -1321,9 +1456,9 @@ } }, "fresh": { - "version": "0.2.4", - "resolved": "http://registry.npm.taobao.org/fresh/download/fresh-0.2.4.tgz", - "integrity": "sha1-NYJJkgbJcjcUGQ7ddLRgT+tKYUw=" + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "fs.realpath": { "version": "1.0.0", @@ -2047,9 +2182,12 @@ } }, "iconv-lite": { - "version": "0.4.8", - "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.8.tgz", - "integrity": "sha1-xgGadZXyzvynAuq2lKAQvNkpjSA=" + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ignore-by-default": { "version": "1.0.1", @@ -2095,9 +2233,9 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.0.5.tgz", - "integrity": "sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c=" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" }, "is-accessor-descriptor": { "version": "0.1.6", @@ -2357,6 +2495,11 @@ "verror": "1.10.0" } }, + "keep-alive-agent": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/keep-alive-agent/-/keep-alive-agent-0.0.1.tgz", + "integrity": "sha1-RIR8o5TOjWtSGuhYFr1kUJlCs4U=" + }, "keygrip": { "version": "1.0.3", "resolved": "http://registry.npm.taobao.org/keygrip/download/keygrip-1.0.3.tgz", @@ -2536,9 +2679,9 @@ "integrity": "sha1-Vms3lo/gxNdro2ptpWT6YTlFynI=" }, "lodash": { - "version": "4.17.11", - "resolved": "http://registry.npm.taobao.org/lodash/download/lodash-4.17.11.tgz", - "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "long": { "version": "3.2.0", @@ -2601,9 +2744,9 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "merge-descriptors": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.0.tgz", - "integrity": "sha1-IWnPdTjhsMyH+4jhUC2EdLv3mGQ=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "methods": { "version": "1.1.2", @@ -2664,9 +2807,9 @@ "dev": true }, "mixin-deep": { - "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.1.tgz", - "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -2675,8 +2818,8 @@ "dependencies": { "is-extendable": { "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -2716,9 +2859,9 @@ } }, "negotiator": { - "version": "0.5.3", - "resolved": "http://registry.npm.taobao.org/negotiator/download/negotiator-0.5.3.tgz", - "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, "nodemailer": { "version": "4.7.0", @@ -2827,11 +2970,11 @@ } }, "on-finished": { - "version": "2.2.1", - "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.2.1.tgz", - "integrity": "sha1-XIXBzDYpn3gCllP2Z/J7a5nrwCk=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "requires": { - "ee-first": "1.1.0" + "ee-first": "1.1.1" } }, "on-headers": { @@ -2913,9 +3056,9 @@ "dev": true }, "path-to-regexp": { - "version": "0.1.3", - "resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.3.tgz", - "integrity": "sha1-IbmrgidCed4lsVbqCP0SylG4rss=" + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "performance-now": { "version": "2.1.0", @@ -2957,12 +3100,12 @@ } }, "proxy-addr": { - "version": "1.0.10", - "resolved": "http://registry.npm.taobao.org/proxy-addr/download/proxy-addr-1.0.10.tgz", - "integrity": "sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", "requires": { - "forwarded": "~0.1.0", - "ipaddr.js": "1.0.5" + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" } }, "pseudomap": { @@ -2993,17 +3136,38 @@ "integrity": "sha1-qZwPaajSa/fvAS+HHNq7Cu5EJMI=" }, "range-parser": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/range-parser/download/range-parser-1.0.3.tgz", - "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "1.3.4", - "resolved": "http://registry.npm.taobao.org/raw-body/download/raw-body-1.3.4.tgz", - "integrity": "sha1-zMfd/Ea3KGHN1btDPIQLcLbyf1Q=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "requires": { - "bytes": "1.0.0", - "iconv-lite": "0.4.8" + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } } }, "rc": { @@ -3176,102 +3340,86 @@ } }, "send": { - "version": "0.12.2", - "resolved": "http://registry.npm.taobao.org/send/download/send-0.12.2.tgz", - "integrity": "sha1-umeF5Hq0GqA1i52kAasi/w9Y6rY=", - "requires": { - "debug": "~2.1.3", - "depd": "~1.0.0", - "destroy": "1.0.3", - "escape-html": "1.0.1", - "etag": "~1.5.1", - "fresh": "0.2.4", - "mime": "1.3.4", - "ms": "0.7.0", - "on-finished": "~2.2.0", - "range-parser": "~1.0.2" + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" }, "dependencies": { "debug": { - "version": "2.1.3", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.1.3.tgz", - "integrity": "sha1-zoqxte6PvuK/o7Yzyrk9NmtjQY4=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "ms": "0.7.0" + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, - "mime": { - "version": "1.3.4", - "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } }, - "ms": { - "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.0.tgz", - "integrity": "sha1-hlvpTC5zl62KV9pqYzpuLzB5i4M=" + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" } } }, "serve-static": { - "version": "1.9.3", - "resolved": "http://registry.npm.taobao.org/serve-static/download/serve-static-1.9.3.tgz", - "integrity": "sha1-X42gcyOtOF/z3FQfGnkXsuQ261c=", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "requires": { - "escape-html": "1.0.1", - "parseurl": "~1.3.0", - "send": "0.12.3", - "utils-merge": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" }, "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "etag": { - "version": "1.6.0", - "resolved": "http://registry.npm.taobao.org/etag/download/etag-1.6.0.tgz", - "integrity": "sha1-i8ssavElTEgd/IuZfJBu9ORCwgc=", - "requires": { - "crc": "3.2.1" - } - }, - "mime": { - "version": "1.3.4", - "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - }, - "send": { - "version": "0.12.3", - "resolved": "http://registry.npm.taobao.org/send/download/send-0.12.3.tgz", - "integrity": "sha1-zRLcWP3iHk+RkCs5sv2gWnptm9w=", - "requires": { - "debug": "~2.2.0", - "depd": "~1.0.1", - "destroy": "1.0.3", - "escape-html": "1.0.1", - "etag": "~1.6.0", - "fresh": "0.2.4", - "mime": "1.3.4", - "ms": "0.7.1", - "on-finished": "~2.2.1", - "range-parser": "~1.0.2" - } + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" } } }, "set-value": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/set-value/download/set-value-2.0.0.tgz", - "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -3311,6 +3459,50 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "optional": true, + "requires": { + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "optional": true, + "requires": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "optional": true + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "optional": true, + "requires": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "optional": true + }, "signal-exit": { "version": "3.0.2", "resolved": "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz", @@ -3636,6 +3828,11 @@ "repeat-string": "^1.6.1" } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "touch": { "version": "3.1.0", "resolved": "http://registry.npm.taobao.org/touch/download/touch-3.1.0.tgz", @@ -3715,38 +3912,15 @@ "integrity": "sha1-BtzjSg5op7q8KbNluOdLiSUgOWE=" }, "union-value": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/union-value/download/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "http://registry.npm.taobao.org/set-value/download/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "unique-string": { @@ -3868,9 +4042,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { "version": "3.3.2", @@ -3878,9 +4052,9 @@ "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE=" }, "vary": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/vary/download/vary-1.0.1.tgz", - "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "verror": { "version": "1.10.0", diff --git a/package.json b/package.json index 54065c3b0..c8d892ad1 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,12 @@ }, "dependencies": { "akismet-api": "^3.0.0", - "body-parser": "1.12.3", + "baidu-aip-sdk": "^2.4.5", + "body-parser": "^1.19.0", "connect-timeout": "^1.7.0", "cookie-parser": "^1.3.5", "ejs": "2.3.1", - "express": "4.12.3", + "express": "^4.17.1", "leancloud-storage": "^3.0.0", "leanengine": "^3.0.0", "nodemailer": "^4.0.1", diff --git a/public/stylesheets/style.min.css b/public/stylesheets/style.min.css new file mode 100644 index 000000000..83de04896 --- /dev/null +++ b/public/stylesheets/style.min.css @@ -0,0 +1 @@ +body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,sans-serif;font-size:1rem}a{text-decoration:none;color:#3eb0ef}.footer{font-size:.8rem}.title{font-weight:200;font-size:1.5rem}ul{list-style:none}li{list-style:none}.content{padding:0}.header{display:flex;-ms-flex-direction:row;flex-direction:row;align-items:flex-start}.header .title{flex:90%}.comment-main{padding:1rem 5rem}.vhead{padding-bottom:.5rem}.vhead #nick,.vhead a{font-weight:bolder;color:#333}.spacer{color:#ccc;margin-left:.3rem;margin-right:.3rem}.vtime{color:#a9a4a4;display:inline-block;padding:0 5px}.vcomment{line-height:1.8}.vcard{padding:2rem 0 2rem 0;border-top:1px solid #dedede}.check{padding-top:1rem;color:#33b1ff}.sign-in-wrap{display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;color:#738a94;font-weight:100;text-align:center;align-items:center;margin-top:4rem}.gh-signup{width:600px!important}.gh-signin{display:flex;-ms-flex-direction:column;flex-direction:column;padding:1rem 2rem;width:350px;border:1px solid #dae1e3;background:#f8fbfd;border-radius:5px;text-align:left}.gh-signin .form-group{margin-bottom:1.5rem;position:relative;width:100%;max-width:700px;-webkit-user-select:text;user-select:text}.sign-in-wrap input{padding:10px;margin:1rem 0;border:1px solid #dae1e3;font-size:1rem;line-height:1.5em;font-weight:100;display:block;user-select:text;border-radius:4px;transition:border-color .15s linear;-webkit-appearance:none;color:#4b5b62;-webkit-user-select:text}.sign-in-wrap input:focus{border-color:#c4c8cb;outline:0}.sign-in-wrap .login-button{padding:8px 10px;cursor:pointer;background:#33b1ff;border:.1rem solid #33b1ff;border-radius:.2rem;color:#fff}.red{color:#ee1000}.blue{padding-left:9px;color:#33b1ff} \ No newline at end of file diff --git a/utilities/check-spam-baidu.js b/utilities/check-spam-baidu.js new file mode 100644 index 000000000..0ff42f385 --- /dev/null +++ b/utilities/check-spam-baidu.js @@ -0,0 +1,69 @@ +'use strict'; +const AV = require('leanengine'); +const baidu = require('baidu-aip-sdk').contentCensor; +const APPID = process.env.BAIDU_APPID, + AK = process.env.BAIDU_APIKEY, + SK = process.env.BAIDU_SECRET; +const baiduClient = new baidu(APPID, AK, SK); + +// 评论审核 +exports.checkSpam = (comment, ip) => { + if (!APPID || APPID === 'MANUAL_REVIEW') { + console.log('未启用或已使用人工审核模式,评论审核后才会发表~'); + comment.setACL(new AV.ACL({ + "*": { + "read": false + } + })); + comment.set('isSpam', true); + comment.save(); + return; + } + if (!AK || !SK) return console.log('Baidu Key 配置异常:'); + + comment.set('ip', ip); + return baiduClient.textCensorUserDefined(comment.get('comment')).then(data => { + console.log(': ' + JSON.stringify(data)); + if (data.error_code != undefined || !data.conclusionType || data.conclusionType == 4) { + return console.log(`垃圾评论检测出错!`) + } + if (data.conclusionType != 1) { + console.log('逮到一只垃圾评论,烧死它!用文火~'); + comment.set('isSpam', true); + comment.setACL(new AV.ACL({ + "*": { + "read": false + } + })); + comment.save(); + // comment.destroy(); + } else { + comment.set('isSpam', false); + comment.setACL(new AV.ACL({ + "*": { + "read": true + } + })); + comment.save(); + console.log('垃圾评论检测完成,放行~'); + } + }, err => { + if (err) console.log(`垃圾评论检测出错!${err}`); + }); +}; + +// 提交黑名单 +exports.submitSpam = (comment) => { + if (!APPID || APPID === 'MANUAL_REVIEW') return; + if (!AK || !SK) return console.log('Baidu Key 配置异常:'); + console.log('请自行前往百度后台配置黑名单:https://ai.baidu.com/censoring'); + //TODO:将黑名单写入LeanCloud便于后续导出整理 +} + +// 提交白名单 +exports.submitHam = (comment) => { + if (!APPID || APPID === 'MANUAL_REVIEW') return; + if (!AK || !SK) return console.log('Baidu Key 配置异常:'); + console.log('请自行前往百度后台配置白名单:https://ai.baidu.com/censoring'); + //TODO:将白名单写入LeanCloud便于后续导出整理 +}; \ No newline at end of file diff --git a/utilities/check-spam.js b/utilities/check-spam.js index 2e6b1cfcc..38dc14393 100644 --- a/utilities/check-spam.js +++ b/utilities/check-spam.js @@ -1,107 +1,128 @@ 'use strict'; +const BD = require('./check-spam-baidu'); const AV = require('leanengine'); const akismet = require('akismet-api'); const akismetClient = akismet.client({ - key : process.env.AKISMET_KEY, - blog : process.env.SITE_URL + key: process.env.AKISMET_KEY, + blog: process.env.SITE_URL }); -exports.checkSpam = (comment, ip)=> { +exports.checkSpam = (comment, ip) => { + if (process.env.BAIDU_APPID != undefined) { + // 由于百度有次数问题,所以尽可能筛查过的就不再筛查。 + if (comment.get('isSpam') == undefined) return BD.checkSpam(comment, ip); + return + } if (process.env.AKISMET_KEY === 'MANUAL_REVIEW') { console.log('已使用人工审核模式,评论审核后才会发表~'); - comment.setACL(new AV.ACL({"*":{"read":false}})); + comment.setACL(new AV.ACL({ + "*": { + "read": false + } + })); comment.set('isSpam', true); comment.save(); return; } - akismetClient.verifyKey(function(err, valid) { + akismetClient.verifyKey(function (err, valid) { if (err) console.log('Akismet key 异常:', err.message); if (valid) { // TODO(1) 这里有缺陷 comment.set('ip', ip); akismetClient.checkSpam({ - user_ip : ip, - user_agent : comment.get('ua'), - referrer : process.env.SITE_URL + comment.get('url'), - permalink : process.env.SITE_URL + comment.get('url'), - comment_type : 'comment', - comment_author : comment.get('nick'), - comment_author_email : comment.get('mail'), - comment_author_url : comment.get('link'), - comment_content : comment.get('comment'), + user_ip: ip, + user_agent: comment.get('ua'), + referrer: process.env.SITE_URL + comment.get('url'), + permalink: process.env.SITE_URL + comment.get('url'), + comment_type: 'comment', + comment_author: comment.get('nick'), + comment_author_email: comment.get('mail'), + comment_author_url: comment.get('link'), + comment_content: comment.get('comment'), // is_test : true // Default value is false - }, function(err, spam) { - if (err) console.log (`垃圾评论检测出错!${err}`); + }, function (err, spam) { + if (err) console.log(`垃圾评论检测出错!${err}`); if (spam) { console.log('逮到一只垃圾评论,烧死它!用文火~'); comment.set('isSpam', true); - comment.setACL(new AV.ACL({"*":{"read":false}})); + comment.setACL(new AV.ACL({ + "*": { + "read": false + } + })); comment.save(); // comment.destroy(); } else { comment.set('isSpam', false); - comment.setACL(new AV.ACL({"*":{"read":true}})); + comment.setACL(new AV.ACL({ + "*": { + "read": true + } + })); comment.save(); console.log('垃圾评论检测完成,放行~'); } }); - } - else console.log('Akismet key 异常!'); + } else console.log('Akismet key 异常!'); }); }; -exports.submitSpam = (comment)=> { +exports.submitSpam = (comment) => { + if (process.env.BAIDU_APPID != undefined) { + return BD.submitSpam(comment); + } if (process.env.AKISMET_KEY === 'MANUAL_REVIEW') { return; } - akismetClient.verifyKey(function(err, valid) { + akismetClient.verifyKey(function (err, valid) { if (err) console.log('Akismet key 异常:', err.message); if (valid) { let ipAddr = comment.get('ip'); akismetClient.submitSpam({ - user_ip : ipAddr, - user_agent : comment.get('ua'), - referrer : process.env.SITE_URL + comment.get('url'), - permalink : process.env.SITE_URL + comment.get('url'), - comment_type : 'comment', - comment_author : comment.get('nick'), - comment_author_email : comment.get('mail'), - comment_author_url : comment.get('link'), - comment_content : comment.get('comment'), + user_ip: ipAddr, + user_agent: comment.get('ua'), + referrer: process.env.SITE_URL + comment.get('url'), + permalink: process.env.SITE_URL + comment.get('url'), + comment_type: 'comment', + comment_author: comment.get('nick'), + comment_author_email: comment.get('mail'), + comment_author_url: comment.get('link'), + comment_content: comment.get('comment'), // is_test : true // Default value is false - }, function(err) { + }, function (err) { if (!err) { console.log('垃圾评论已经提交!'); } }); - } - else console.log('Akismet key 异常!'); + } else console.log('Akismet key 异常!'); }); }; -exports.submitHam = (comment)=> { +exports.submitHam = (comment) => { + if (process.env.BAIDU_APPID != undefined) { + return BD.submitHam(comment); + } if (process.env.AKISMET_KEY === 'MANUAL_REVIEW') { return; } - akismetClient.verifyKey(function(err, valid) { + akismetClient.verifyKey(function (err, valid) { if (err) console.log('Akismet key 异常:', err.message); if (valid) { let ipAddr = comment.get('ip'); akismetClient.submitHam({ - user_ip : ipAddr, - user_agent : comment.get('ua'), - referrer : process.env.SITE_URL + comment.get('url'), - permalink : process.env.SITE_URL + comment.get('url'), - comment_type : 'comment', - comment_author : comment.get('nick'), - comment_author_email : comment.get('mail'), - comment_author_url : comment.get('link'), - comment_content : comment.get('comment'), + user_ip: ipAddr, + user_agent: comment.get('ua'), + referrer: process.env.SITE_URL + comment.get('url'), + permalink: process.env.SITE_URL + comment.get('url'), + comment_type: 'comment', + comment_author: comment.get('nick'), + comment_author_email: comment.get('mail'), + comment_author_url: comment.get('link'), + comment_content: comment.get('comment'), // is_test : true // Default value is false - }, function(err) { + }, function (err) { if (!err) { console.log('评论已经标记为非垃圾!'); } }); - } - else console.log('Akismet key 异常!'); + } else console.log('Akismet key 异常!'); }); -}; +}; \ No newline at end of file diff --git a/views/comments.ejs b/views/comments.ejs index 2e785da5c..b60f6c573 100644 --- a/views/comments.ejs +++ b/views/comments.ejs @@ -2,7 +2,7 @@ <%= title %> - +
@@ -38,7 +38,7 @@
<% if(comment_list[i].get('isSpam')) { %> - 这不是垃圾评论 + 这不是垃圾评论 <% } else { %> 标记为垃圾评论 <% } %> diff --git a/views/error.ejs b/views/error.ejs index bbd2765d5..34e309b3e 100644 --- a/views/error.ejs +++ b/views/error.ejs @@ -2,7 +2,7 @@ Error - +

<%= message %>

diff --git a/views/index.ejs b/views/index.ejs index 99657a42d..a44752391 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -2,7 +2,7 @@ LeanCloud评论管理 - + diff --git a/views/sign-up.ejs b/views/sign-up.ejs index bf429711e..f68435221 100644 --- a/views/sign-up.ejs +++ b/views/sign-up.ejs @@ -2,7 +2,7 @@ LeanCloud评论管理 - +