Skip to content

Commit ce56745

Browse files
authored
feat: update prismjs, add ip region #366 #368
* chore: update prismjs * feat: ip region
1 parent 08f95ed commit ce56745

File tree

17 files changed

+142
-42
lines changed

17 files changed

+142
-42
lines changed

cloudbaserc.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
{
77
"name": "twikoo",
88
"timeout": 30,
9-
"runtime": "Nodejs10.15",
9+
"runtime": "Nodejs12.16",
1010
"memorySize": 128,
1111
"handler": "index.main"
1212
}
@@ -23,7 +23,7 @@
2323
"name": "twikoo",
2424
"timeout": 30,
2525
"envVariables": {},
26-
"runtime": "Nodejs10.15",
26+
"runtime": "Nodejs12.16",
2727
"memory": 128
2828
}
2929
],

docs/.vuepress/theme/layouts/Layout.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
<!-- Twikoo -->
1515
<div id="twikoo"></div>
16-
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.8/dist/twikoo.all.min.js" ref="twikooJs"></script>
16+
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.9/dist/twikoo.all.min.js" ref="twikooJs"></script>
1717
</div>
1818
</template>
1919
</ParentLayout>

docs/quick-start.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ exports.main = require('twikoo-func').main
4444
8. 创建完成后,点击“twikoo"进入云函数详情页,进入“函数代码”标签,点击“文件 - 新建文件”,输入 `package.json`,回车
4545
9. 复制以下代码、粘贴到代码框中,点击“保存并安装依赖”
4646
``` json
47-
{ "dependencies": { "twikoo-func": "1.5.8" } }
47+
{ "dependencies": { "twikoo-func": "1.5.9" } }
4848
```
4949

5050
### 命令行部署
@@ -175,7 +175,7 @@ twikoo:
175175

176176
``` html
177177
<div id="tcomment"></div>
178-
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.8/dist/twikoo.all.min.js"></script>
178+
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.9/dist/twikoo.all.min.js"></script>
179179
<script>
180180
twikoo.init({
181181
envId: '您的环境id', // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app)
@@ -193,7 +193,7 @@ twikoo.init({
193193

194194
请参考爆米兔前端静态资源库 [https://cdn.baomitu.com/twikoo](https://cdn.baomitu.com/twikoo)
195195

196-
引入的 CDN 链接替换为如下即可:`https://lib.baomitu.com/twikoo/1.5.8/twikoo.all.min.js`
196+
引入的 CDN 链接替换为如下即可:`https://lib.baomitu.com/twikoo/1.5.9/twikoo.all.min.js`
197197

198198
## 开启管理面板
199199

package.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
{
22
"name": "twikoo",
3-
"version": "1.5.8",
3+
"version": "1.5.9",
44
"description": "A simple comment system based on Tencent CloudBase (tcb).",
5-
"keywords": ["twikoojs", "comment", "comment-system", "cloudbase", "vercel"],
5+
"keywords": [
6+
"twikoojs",
7+
"comment",
8+
"comment-system",
9+
"cloudbase",
10+
"vercel"
11+
],
612
"author": "imaegoo <hello@imaegoo.com> (https://github.com/imaegoo)",
713
"license": "MIT",
814
"main": "./dist/twikoo.all.min.js",
@@ -51,7 +57,7 @@
5157
"eslint-plugin-vue": "^8.0.3",
5258
"marked": "^4.0.12",
5359
"owo": "^1.0.2",
54-
"prismjs": "^1.25.0",
60+
"prismjs": "^1.28.0",
5561
"svg-inline-loader": "^0.8.2",
5662
"terser-webpack-plugin": "^5.2.5",
5763
"vue": "^2.6.14",

src/function/twikoo/index.js

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const CryptoJS = require('crypto-js') // 编解码
2121
const tencentcloud = require('tencentcloud-sdk-nodejs') // 腾讯云 API NODEJS SDK
2222
const fs = require('fs')
2323
const FormData = require('form-data') // 图片上传
24-
const pushoo = require('pushoo').default
24+
const pushoo = require('pushoo').default // 即时消息通知
25+
const ipToRegion = require('dy-node-ip2region') // IP 属地查询
2526

2627
// 云函数 SDK / tencent cloudbase sdk
2728
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV })
@@ -33,6 +34,9 @@ const _ = db.command
3334
const window = new JSDOM('').window
3435
const DOMPurify = createDOMPurify(window)
3536

37+
// 初始化 IP 属地
38+
const ipRegionSearcher = ipToRegion.create()
39+
3640
// 常量 / constants
3741
const RES_CODE = {
3842
SUCCESS: 0,
@@ -343,13 +347,15 @@ function parseComment (comments, uid) {
343347
function toCommentDto (comment, uid, replies = [], comments = []) {
344348
let displayOs = ''
345349
let displayBrowser = ''
346-
try {
347-
const ua = bowser.getParser(comment.ua)
348-
const os = ua.getOS()
349-
displayOs = [os.name, os.versionName ? os.versionName : os.version].join(' ')
350-
displayBrowser = [ua.getBrowserName(), ua.getBrowserVersion()].join(' ')
351-
} catch (e) {
352-
console.log('bowser 错误:', e)
350+
if (config.SHOW_UA !== 'false') {
351+
try {
352+
const ua = bowser.getParser(comment.ua)
353+
const os = ua.getOS()
354+
displayOs = [os.name, os.versionName ? os.versionName : os.version].join(' ')
355+
displayBrowser = [ua.getBrowserName(), ua.getBrowserVersion()].join(' ')
356+
} catch (e) {
357+
console.log('bowser 错误:', e)
358+
}
353359
}
354360
return {
355361
id: comment._id,
@@ -360,6 +366,7 @@ function toCommentDto (comment, uid, replies = [], comments = []) {
360366
comment: comment.comment,
361367
os: displayOs,
362368
browser: displayBrowser,
369+
ipRegion: config.SHOW_REGION ? getIpRegion({ ip: comment.ip }) : '',
363370
master: comment.master,
364371
like: comment.like ? comment.like.length : 0,
365372
liked: comment.like ? comment.like.findIndex((item) => item === uid) > -1 : false,
@@ -440,7 +447,7 @@ function getCommentSearchCondition (event) {
440447

441448
function parseCommentForAdmin (comments) {
442449
for (const comment of comments) {
443-
comment.commentText = $(comment.comment).text()
450+
comment.ipRegion = getIpRegion({ ip: comment.ip, detail: true })
444451
}
445452
return comments
446453
}
@@ -1652,6 +1659,27 @@ async function isAdmin () {
16521659
return ADMIN_USER_ID === userInfo.userInfo.customUserId
16531660
}
16541661

1662+
/**
1663+
* 获取 IP 属地
1664+
* @param detail true 返回省市运营商,false 只返回省
1665+
* @returns {String}
1666+
*/
1667+
function getIpRegion ({ ip, detail = false }) {
1668+
if (!ip) return ''
1669+
try {
1670+
const { region } = ipRegionSearcher.btreeSearchSync(ip)
1671+
const [,, province, city, isp] = region.split('|')
1672+
if (detail) {
1673+
return province === city ? [city, isp].join(' ') : [province, city, isp].join(' ')
1674+
} else {
1675+
return province
1676+
}
1677+
} catch (e) {
1678+
console.error('IP 属地查询失败:', e)
1679+
return ''
1680+
}
1681+
}
1682+
16551683
// 判断是否为递归调用(即云函数调用自身)
16561684
function isRecursion (context) {
16571685
const envObj = tcb.getCloudbaseContext(context)

src/function/twikoo/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twikoo-func",
3-
"version": "1.5.8",
3+
"version": "1.5.9",
44
"description": "A simple comment system based on Tencent CloudBase (tcb).",
55
"author": "imaegoo <hello@imaegoo.com> (https://github.com/imaegoo)",
66
"license": "MIT",
@@ -20,6 +20,7 @@
2020
"cheerio": "1.0.0-rc.5",
2121
"crypto-js": "^4.0.0",
2222
"dompurify": "^2.2.6",
23+
"dy-node-ip2region": "^1.0.1",
2324
"form-data": "^4.0.0",
2425
"jsdom": "^16.4.0",
2526
"marked": "^4.0.12",

src/js/entites/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class Config {
4444
this.MAIL_TEMPLATE = model.MAIL_TEMPLATE
4545
this.MAIL_SUBJECT_ADMIN = model.MAIL_SUBJECT_ADMIN
4646
this.MAIL_TEMPLATE_ADMIN = model.MAIL_TEMPLATE_ADMIN
47+
this.SHOW_UA = model.SHOW_UA
48+
this.SHOW_REGION = model.SHOW_REGION
4749
}
4850
}
4951

src/js/utils/highlight.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { app } from '../../view'
22

3-
const PRISM_CDN = 'https://cdn.jsdelivr.net/npm/prismjs@1.23.0'
3+
const PRISM_CDN = 'https://cdn.jsdelivr.net/npm/prismjs@1.28.0'
44
let Prism
55
let cssEl
66

@@ -22,9 +22,9 @@ const loadCss = (theme, prismCdn) => {
2222
if ((cssEl && twikooEl.contains(cssEl)) || !theme || theme === 'none') return
2323
cssEl = document.createElement('link')
2424
if (theme === 'default') {
25-
cssEl.href = `${prismCdn}/themes/prism.css`
25+
cssEl.href = `${prismCdn}/themes/prism.min.css`
2626
} else {
27-
cssEl.href = `${prismCdn}/themes/prism-${theme}.css`
27+
cssEl.href = `${prismCdn}/themes/prism-${theme}.min.css`
2828
}
2929
cssEl.rel = 'stylesheet'
3030
cssEl.type = 'text/css'

src/js/utils/i18n/i18n.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,12 @@ export default {
236236
'外掛',
237237
'Plugin'
238238
],
239+
[S.ACC + '_PRIVACY']: [
240+
'隐私',
241+
'隱私',
242+
'隱私',
243+
'Privacy'
244+
],
239245
[S.ACC + '_SPAM']: [
240246
'反垃圾',
241247
'反垃圾',
@@ -482,6 +488,18 @@ export default {
482488
'啟用插入圖片功能,預設為:true',
483489
'Enable picture uploading. Default: true.'
484490
],
491+
[S.ACI + '_SHOW_UA']: [
492+
'是否显示用户系统和浏览器,默认为:true',
493+
'是否顯示使用者系統和瀏覽器,預設為:true',
494+
'是否顯示使用者系統和瀏覽器,預設為:true',
495+
'Show users\' OS and browser. Default: true.'
496+
],
497+
[S.ACI + '_SHOW_REGION']: [
498+
'是否显示用户 IP 属地到省,默认为:false',
499+
'是否顯示使用者 IP 屬地到省,預設為:false',
500+
'是否顯示使用者 IP 屬地到省,預設為:false',
501+
'Show users\' IP region (province). Default: false.'
502+
],
485503
[S.ACI + '_SITE_NAME']: [
486504
'网站名称',
487505
'網站名稱',

src/vercel-min/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "dependencies": { "twikoo-vercel": "1.5.8" } }
1+
{ "dependencies": { "twikoo-vercel": "1.5.9" } }

src/vercel/api/index.js

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@ const tencentcloud = require('tencentcloud-sdk-nodejs') // 腾讯云 API NODEJS
2323
const { v4: uuidv4 } = require('uuid') // 用户 id 生成
2424
const fs = require('fs')
2525
const FormData = require('form-data') // 图片上传
26-
const pushoo = require('pushoo').default
26+
const pushoo = require('pushoo').default // 即时消息通知
27+
const ipToRegion = require('dy-node-ip2region') // IP 属地查询
2728

2829
// 初始化反 XSS
2930
const window = new JSDOM('').window
3031
const DOMPurify = createDOMPurify(window)
3132

33+
// 初始化 IP 属地
34+
const ipRegionSearcher = ipToRegion.create()
35+
3236
// 常量 / constants
3337
const RES_CODE = {
3438
SUCCESS: 0,
@@ -375,13 +379,15 @@ function parseComment (comments, uid) {
375379
function toCommentDto (comment, uid, replies = [], comments = []) {
376380
let displayOs = ''
377381
let displayBrowser = ''
378-
try {
379-
const ua = bowser.getParser(comment.ua)
380-
const os = ua.getOS()
381-
displayOs = [os.name, os.versionName ? os.versionName : os.version].join(' ')
382-
displayBrowser = [ua.getBrowserName(), ua.getBrowserVersion()].join(' ')
383-
} catch (e) {
384-
console.log('bowser 错误:', e)
382+
if (config.SHOW_UA !== 'false') {
383+
try {
384+
const ua = bowser.getParser(comment.ua)
385+
const os = ua.getOS()
386+
displayOs = [os.name, os.versionName ? os.versionName : os.version].join(' ')
387+
displayBrowser = [ua.getBrowserName(), ua.getBrowserVersion()].join(' ')
388+
} catch (e) {
389+
console.log('bowser 错误:', e)
390+
}
385391
}
386392
return {
387393
id: comment._id.toString(),
@@ -392,6 +398,7 @@ function toCommentDto (comment, uid, replies = [], comments = []) {
392398
comment: comment.comment,
393399
os: displayOs,
394400
browser: displayBrowser,
401+
ipRegion: config.SHOW_REGION ? getIpRegion({ ip: comment.ip }) : '',
395402
master: comment.master,
396403
like: comment.like ? comment.like.length : 0,
397404
liked: comment.like ? comment.like.findIndex((item) => item === uid) > -1 : false,
@@ -472,7 +479,7 @@ function getCommentSearchCondition (event) {
472479

473480
function parseCommentForAdmin (comments) {
474481
for (const comment of comments) {
475-
comment.commentText = $(comment.comment).text()
482+
comment.ipRegion = getIpRegion({ ip: comment.ip, detail: true })
476483
}
477484
return comments
478485
}
@@ -1667,6 +1674,27 @@ async function isAdmin () {
16671674
return config.ADMIN_PASS === md5(uid)
16681675
}
16691676

1677+
/**
1678+
* 获取 IP 属地
1679+
* @param detail true 返回省市运营商,false 只返回省
1680+
* @returns {String}
1681+
*/
1682+
function getIpRegion ({ ip, detail = false }) {
1683+
if (!ip) return ''
1684+
try {
1685+
const { region } = ipRegionSearcher.btreeSearchSync(ip)
1686+
const [,, province, city, isp] = region.split('|')
1687+
if (detail) {
1688+
return province === city ? [city, isp].join(' ') : [province, city, isp].join(' ')
1689+
} else {
1690+
return province
1691+
}
1692+
} catch (e) {
1693+
console.error('IP 属地查询失败:', e)
1694+
return ''
1695+
}
1696+
}
1697+
16701698
// 判断是否为递归调用(即云函数调用自身)
16711699
function isRecursion () {
16721700
return request.headers['x-twikoo-recursion'] === (config.ADMIN_PASS || 'true')

src/vercel/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twikoo-vercel",
3-
"version": "1.5.8",
3+
"version": "1.5.9",
44
"description": "A simple comment system based on Tencent CloudBase (tcb).",
55
"author": "imaegoo <hello@imaegoo.com> (https://github.com/imaegoo)",
66
"license": "MIT",
@@ -18,6 +18,7 @@
1818
"cheerio": "1.0.0-rc.5",
1919
"crypto-js": "^4.0.0",
2020
"dompurify": "^2.2.6",
21+
"dy-node-ip2region": "^1.0.1",
2122
"form-data": "^4.0.0",
2223
"jsdom": "^16.4.0",
2324
"marked": "^4.0.12",

src/version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
const version = '1.5.8'
1+
const version = '1.5.9'
22

33
export { version }

src/view/components/TkAdminComment.vue

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
<div class="tk-admin-comment-item" v-for="comment in comments" :key="comment._id">
2424
<div class="tk-admin-comment-meta">
2525
<tk-avatar :config="serverConfig" :avatar="comment.avatar" :mail="comment.mail" :link="comment.link" />
26-
<span v-if="!comment.link">{{ comment.nick }}</span>
27-
<a v-if="comment.link" :href="convertLink(comment.link)" target="_blank">{{ comment.nick }}</a>
28-
<span v-if="comment.mail">&nbsp;(<a :href="`mailto:${comment.mail}`">{{ comment.mail }}</a>)</span>
29-
<span v-if="comment.isSpam">{{ t('ADMIN_COMMENT_IS_SPAM_SUFFIX') }}</span>
30-
<span class="tk-time">&nbsp;{{ displayCreated(comment) }}</span>
26+
<span v-if="!comment.link">{{ comment.nick }}&nbsp;</span>
27+
<a v-if="comment.link" :href="convertLink(comment.link)" target="_blank">{{ comment.nick }}&nbsp;</a>
28+
<span v-if="comment.mail">(<a :href="`mailto:${comment.mail}`">{{ comment.mail }}</a>)&nbsp;</span>
29+
<span v-if="comment.isSpam">{{ t('ADMIN_COMMENT_IS_SPAM_SUFFIX') }}&nbsp;</span>
30+
<span class="tk-time">{{ displayCreated(comment) }}&nbsp;</span>
31+
<span>{{ comment.ipRegion }}</span>
3132
</div>
3233
<div class="tk-content" v-html="comment.comment" ref="comments"></div>
3334
<div class="tk-admin-actions">
@@ -240,6 +241,7 @@ export default {
240241
.tk-admin-comment-meta {
241242
display: flex;
242243
align-items: center;
244+
flex-wrap: wrap;
243245
margin-bottom: 0.5em;
244246
}
245247
.tk-avatar {

src/view/components/TkAdminConfig.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ export default {
7777
{ key: 'HIGHLIGHT_THEME', desc: t('ADMIN_CONFIG_ITEM_HIGHLIGHT_THEME'), ph: `${t('ADMIN_CONFIG_EXAMPLE')}tomorrow`, value: '' }
7878
]
7979
},
80+
{
81+
name: t('ADMIN_CONFIG_CATEGORY_PRIVACY'),
82+
items: [
83+
{ key: 'SHOW_UA', desc: t('ADMIN_CONFIG_ITEM_SHOW_UA'), ph: `${t('ADMIN_CONFIG_EXAMPLE')}false`, value: '' },
84+
{ key: 'SHOW_REGION', desc: t('ADMIN_CONFIG_ITEM_SHOW_REGION'), ph: `${t('ADMIN_CONFIG_EXAMPLE')}true`, value: '' }
85+
]
86+
},
8087
{
8188
name: t('ADMIN_CONFIG_CATEGORY_SPAM'),
8289
items: [

0 commit comments

Comments
 (0)