Skip to content

Commit 19ada0a

Browse files
committed
New test
1 parent 7eb6ee8 commit 19ada0a

File tree

9 files changed

+823
-11
lines changed

9 files changed

+823
-11
lines changed

api/invisibilitytest.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { get } from 'https';
2+
3+
// 如果长度不等于 28 且不是字母与数字的组合,则返回 false
4+
function isValidUserID(userID) {
5+
return userID.length === 28 && /^[a-zA-Z0-9]+$/.test(userID);
6+
}
7+
8+
export default (req, res) => {
9+
10+
// 限制只能从指定域名访问
11+
const allowedDomains = ['localhost', ...(process.env.ALLOWED_DOMAINS || '').split(',')];
12+
const referer = req.headers.referer;
13+
14+
if (referer) {
15+
const domain = new URL(referer).hostname;
16+
if (!allowedDomains.includes(domain)) {
17+
return res.status(403).json({ error: 'Access denied' });
18+
}
19+
} else {
20+
return res.status(403).json({ error: 'What are you doing?' });
21+
}
22+
23+
const id = req.query.id;
24+
if (!id) {
25+
return res.status(400).json({ error: 'No ID provided' });
26+
}
27+
28+
// 检查 IP 地址是否合法
29+
if (!isValidUserID(id)) {
30+
return res.status(400).json({ error: 'Invalid ID' });
31+
}
32+
33+
const apikey = process.env.INVISIBILITY_TEST_API_KEY;
34+
const url = new URL(`https://proxydetect.ipcheck.ing/getinfo/${id}?apikey=${apikey}`);
35+
36+
get(url, apiRes => {
37+
let data = '';
38+
apiRes.on('data', chunk => data += chunk);
39+
apiRes.on('end', () => {
40+
try {
41+
const result = JSON.parse(data);
42+
res.json(result);
43+
} catch (e) {
44+
res.status(500).json({ error: 'Error parsing JSON' });
45+
}
46+
});
47+
}).on('error', (e) => {
48+
res.status(500).json({ error: e.message });
49+
});
50+
};

server.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import rateLimit from 'express-rate-limit';
1717
import { slowDown } from 'express-slow-down'
1818
import whois from './api/whois.js';
1919
import ipapiisHandler from './api/ipapiis.js';
20+
import invisibilitytestHandler from './api/invisibilitytest.js';
2021

2122
dotenv.config();
2223

@@ -135,6 +136,7 @@ app.get('/api/recaptcha', recaptchaHandler);
135136
app.get('/api/dnsresolver', dnsResolver);
136137
app.get('/api/whois', whois);
137138
app.get('/api/ipapiis', ipapiisHandler);
139+
app.get('/api/invisibility', invisibilitytestHandler);
138140

139141
// 使用查询参数处理所有配置请求
140142
app.get('/api/configs', validateConfigs);

src/App.vue

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,22 @@ export default {
526526
},
527527
];
528528
529+
const invisibilitytest = [
530+
{
531+
keys: "i",
532+
action: () => {
533+
this.scrollToElement("AdvancedTools", 80);
534+
this.$refs.advancedToolsRef.navigateAndToggleOffcanvas('/invisibilitytest');
535+
this.$trackEvent('Nav', 'NavClick', 'InvisibilityTest');
536+
},
537+
description: this.$t('shortcutKeys.InvisibilityTest'),
538+
},
539+
];
540+
541+
if (this.configs.originalSite) {
542+
shortcutConfig.push(...invisibilitytest);
543+
}
544+
529545
shortcutConfig.forEach(config => mappingKeys(config));
530546
},
531547
@@ -585,10 +601,13 @@ export default {
585601
586602
},
587603
mounted() {
588-
this.registerShortcutKeys();
589604
this.setupModalFocus();
590-
this.keyMap = keyMap;
591-
this.sendKeyMap();
605+
setTimeout(() => {
606+
this.registerShortcutKeys();
607+
this.keyMap = keyMap;
608+
this.sendKeyMap();
609+
}, 2000);
610+
592611
this.setInfosLoaded();
593612
this.listenOffcanvas();
594613
window.addEventListener('scroll', this.checkSectionsAndTrack);

src/components/advancedtools.vue

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
</div>
2424
<div :data-bs-theme="isDarkMode ? 'dark' : ''" class="offcanvas offcanvas-bottom" tabindex="-1"
2525
:class="[isMobile ? 'h-100' : 'jn-h']" id="offcanvasTools" aria-labelledby="offcanvasToolsLabel">
26-
<div class="offcanvas-header d-flex justify-content-end" :class="[ showTitle ? 'jn-offcanvas-header':'jn-offcanvas-header-noborder']">
26+
<div class="offcanvas-header d-flex justify-content-end"
27+
:class="[showTitle ? 'jn-offcanvas-header' : 'jn-offcanvas-header-noborder']">
2728
<button v-if="!isMobile" type="button" class="btn opacity-50 jn-bold" @click="fullScreen">
2829
<span v-if="!isFullScreen">
2930
<i class="bi bi-arrows-fullscreen"></i>
@@ -34,7 +35,8 @@
3435
</button>
3536
<Transition name="slide-fade">
3637
<span v-if="showTitle" class="fw-medium"
37-
:class="[isMobile ? 'mobile-h2 text-left' : 'fs-5 text-center ms-auto']">{{ cards[openedCard].icon }}
38+
:class="[isMobile ? 'mobile-h2 text-left' : 'fs-5 text-center ms-auto']">{{
39+
cards[openedCard].icon }}
3840
{{ $t(cards[openedCard].titleKey) }}</span>
3941
</Transition>
4042

@@ -61,11 +63,13 @@ export default {
6163
const store = useStore();
6264
const isDarkMode = computed(() => store.state.isDarkMode);
6365
const isMobile = computed(() => store.state.isMobile);
66+
const configs = computed(() => store.state.configs);
6467
6568
6669
return {
6770
isDarkMode,
6871
isMobile,
72+
configs,
6973
};
7074
},
7175
@@ -79,6 +83,7 @@ export default {
7983
{ path: '/censorshipcheck', icon: '🚧', titleKey: 'censorshipcheck.Title', noteKey: 'advancedtools.CensorshipCheck' },
8084
{ path: '/whois', icon: '📓', titleKey: 'whois.Title', noteKey: 'advancedtools.Whois' },
8185
],
86+
cardInvisibilityTest: { path: '/invisibilitytest', icon: '🫣', titleKey: 'invisibilitytest.Title', noteKey: 'advancedtools.InvisibilityTest' },
8287
isFullScreen: false,
8388
showTitle: false,
8489
openedCard: null,
@@ -121,6 +126,10 @@ export default {
121126
this.$trackEvent('Nav', 'NavClick', 'Whois');
122127
this.openedCard = 5;
123128
break;
129+
case '/invisibilitytest':
130+
this.$trackEvent('Nav', 'NavClick', 'InvisibilityTest');
131+
this.openedCard = 6;
132+
break;
124133
}
125134
var offcanvas = new Offcanvas(document.getElementById('offcanvasTools'));
126135
offcanvas.show();
@@ -146,6 +155,14 @@ export default {
146155
},
147156
mounted() {
148157
this.$refs.scrollContainer.addEventListener('scroll', this.handleScroll);
158+
159+
setTimeout(() => {
160+
if (this.configs.originalSite) {
161+
this.cards.push(this.cardInvisibilityTest);
162+
}
163+
}, 2000);
164+
165+
149166
},
150167
unmounted() {
151168
this.$refs.scrollContainer.removeEventListener('scroll', this.handleScroll);

0 commit comments

Comments
 (0)