Skip to content
Merged
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ DOMAIN,ptest-8.ipcheck.ing,Proxy8

As an open source project, I'm very grateful to the following sponsors for their support:

<a href="https://www.rapidproxy.io/?ref=myip"><img src="https://res.ipcheck.ing/img/rapid_proxy_logo.png" width="240px" title="RapidProxy — Global Residential Proxy Service, covering 90+ million residential IPs, supporting smart rotation, stable sessions, and precise geolocation for proxy testing, browser automation, and data collection. Starting at $0.55/GB, use RAPID10 for 10% off." /></a>

<a href="https://www.digitalocean.com/?refcode=fd2634a3981b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://res.ipcheck.ing/img/digitalocean_logo.png" width="240px" title="DigitalOcean" /></a>

<a href="https://www.1password.com"><img src="https://res.ipcheck.ing/img/1password_logo.png" alt="1Password" title="1Password" width="240px" /></a>
Expand Down
2 changes: 2 additions & 0 deletions README_FR.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ DOMAIN,ptest-8.ipcheck.ing,Proxy8

En tant que projet open source, je suis très reconnaissant aux sponsors suivants pour leur soutien :

<a href="https://www.rapidproxy.io/?ref=myip"><img src="https://res.ipcheck.ing/img/rapid_proxy_logo.png" width="240px" title="RapidProxy — Service de proxy résidentiel mondial, couvrant 90+ millions d'IP résidentielles, offrant la rotation intelligente, les sessions stables et la géolocalisation précise pour le test de proxy, l'automatisation du navigateur et la collecte de données. À partir de $0.55/GB, utilisez RAPID10 pour 10% de réduction." /></a>

<a href="https://www.digitalocean.com/?refcode=fd2634a3981b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://res.ipcheck.ing/img/digitalocean_logo.png" width="240px" title="DigitalOcean" /></a>

<a href="https://www.1password.com"><img src="https://res.ipcheck.ing/img/1password_logo.png" alt="1Password" title="1Password" width="240px" /></a>
Expand Down
2 changes: 2 additions & 0 deletions README_PT-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ DOMAIN,ptest-8.ipcheck.ing,Proxy8

Como projeto de código aberto, sou muito grato aos seguintes patrocinadores pelo apoio:

<a href="https://www.rapidproxy.io/?ref=myip"><img src="https://res.ipcheck.ing/img/rapid_proxy_logo.png" width="240px" title="RapidProxy — Serviço de proxy residencial global, cobrindo 90+ milhões de IPs residenciais, oferecendo rotação inteligente, sessões estáveis e geolocalização precisa para teste de proxy, automação de navegador e coleta de dados. A partir de $0.55/GB, use RAPID10 para 10% de desconto." /></a>

<a href="https://www.digitalocean.com/?refcode=fd2634a3981b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://res.ipcheck.ing/img/digitalocean_logo.png" width="240px" title="DigitalOcean" /></a>

<a href="https://www.1password.com"><img src="https://res.ipcheck.ing/img/1password_logo.png" alt="1Password" title="1Password" width="240px" /></a>
Expand Down
2 changes: 2 additions & 0 deletions README_RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ DOMAIN,ptest-8.ipcheck.ing,Proxy8

Как автор проекта с открытым исходным кодом, я очень благодарен следующим спонсорам за поддержку:

<a href="https://www.rapidproxy.io/?ref=myip"><img src="https://res.ipcheck.ing/img/rapid_proxy_logo.png" width="240px" title="RapidProxy — Глобальный сервис прокси-сервисов для домашнего использования, предоставляющий доступ к 90+ миллионам частных IP-адресов. Поддерживает интеллектуальную ротацию, стабильные сессии и точную геолокацию для тестирования прокси, автоматизации браузера и сбора данных. Начало с $0.55/GB, используйте RAPID10 для 10% скидки." /></a>

<a href="https://www.digitalocean.com/?refcode=fd2634a3981b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://res.ipcheck.ing/img/digitalocean_logo.png" width="240px" title="DigitalOcean" /></a>

<a href="https://www.1password.com"><img src="https://res.ipcheck.ing/img/1password_logo.png" alt="1Password" title="1Password" width="240px" /></a>
Expand Down
2 changes: 2 additions & 0 deletions README_ZH-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ DOMAIN,ptest-8.ipcheck.ing,Proxy8

作為一個開源專案,我非常感謝以下贊助者對我的支持:

<a href="https://www.rapidproxy.io/?ref=myip"><img src="https://res.ipcheck.ing/img/rapid_proxy_logo.png" width="240px" title="RapidProxy — 全球住宅代理服務,覆蓋 9000 萬+ 住宅 IP,支持智能輪換、穩定會話和精確地理定位,適用於代理測試、瀏覽器自動化及數據採集等場景。低至 $0.55/GB,使用 RAPID10 享 9 折優惠" /></a>

<a href="https://www.digitalocean.com/?refcode=fd2634a3981b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://res.ipcheck.ing/img/digitalocean_logo.png" width="240px" title="DigitalOcean" /></a>

<a href="https://www.1password.com"><img src="https://res.ipcheck.ing/img/1password_logo.png" alt="1Password" title="1Password" width="240px" /></a>
Expand Down
2 changes: 2 additions & 0 deletions README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ DOMAIN,ptest-8.ipcheck.ing,Proxy8

作为一个开源项目,我非常感谢以下赞助者对我的支持:

<a href="https://www.rapidproxy.io/?ref=myip"><img src="https://res.ipcheck.ing/img/rapid_proxy_logo.png" width="240px" title="RapidProxy — 全球住宅代理服务,覆盖 9000万+ 住宅 IP,支持智能轮换、稳定会话和精准地理定位,适用于代理测试、浏览器自动化及数据采集等场景。低至 $0.55/GB,使用 RAPID10 享 9 折优惠" /></a>

<a href="https://www.digitalocean.com/?refcode=fd2634a3981b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://res.ipcheck.ing/img/digitalocean_logo.png" width="240px" title="DigitalOcean" /></a>

<a href="https://www.1password.com"><img src="https://res.ipcheck.ing/img/1password_logo.png" alt="1Password" title="1Password" width="240px" /></a>
Expand Down
21 changes: 16 additions & 5 deletions common/report-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

import { isValidIP, isIPv6, isValidDomain } from './valid-ip.js';

export const REPORT_VERSION = 1;
// Bumped on breaking section changes; a viewer only renders its own version
// (older links show the unsupported state — reports live at most 7 days).
// 2: ipinfo cards' isProxy / proxy* fields became anonymity / anonymity*.
export const REPORT_VERSION = 2;

// TTL choices offered at creation time (days) — shared by the share dialog
// and the backend. The first entry (1 day) is the default AND the value the
Expand All @@ -21,6 +24,14 @@ export const REPORT_TTL_DAYS = [1, 3, 7];
// bounding what one KV key can cost. KV's own value limit (25MB) is far away.
export const REPORT_MAX_BYTES = 256 * 1024;

// Anonymity verdict codes for ipinfo cards — made by
// utils/transform-ip-data.js, shared by the builder whitelist and the schema
// enum below.
export const ANONYMITY_CODES = [
'tor', 'relay', 'residential', 'suspected_residential',
'proxy', 'proxy_suspected', 'vpn', 'vpn_suspected', 'none',
];

// Connectivity status codes — single source shared by the recording component
// (ConnectivityTest.vue), the builder whitelist (utils/report-builders.js)
// and the schema enum below, so a rename can't drift them apart.
Expand Down Expand Up @@ -142,13 +153,13 @@ const SECTION_SPECS = {
isp: opt(str(128)),
// IPCheck.ing-source enrichments — absent on other sources, when
// the upstream sign-in-gates them, or when the value is 'unknown'
// (an unknown verdict carries no diagnostic signal).
isProxy: opt(oneOf('yes', 'maybe', 'no')),
// (an unknown line type carries no diagnostic signal).
anonymity: opt(oneOf(...ANONYMITY_CODES)),
ipType: opt(oneOf('business', 'residential', 'wireless', 'hosting')),
nativeIP: opt(bool()),
qualityScore: opt(num(0, 100)),
proxyProtocol: opt(str(32)),
proxyProvider: opt(str(64)),
anonymityProtocol: opt(str(32)),
anonymityProvider: opt(str(64)),
})),
}),
connectivity: obj({
Expand Down
1 change: 1 addition & 0 deletions frontend/components/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ const acknowledgementsList = [
{ name: 'Cloudflare Speedtest', link: 'https://github.com/cloudflare/speedtest' },
{ name: 'DigitalOcean', link: 'https://www.digitalocean.com/?refcode=fd2634a3981b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge' },
{ name: 'V.PS', link: 'https://v.ps/?utm_source=ipcheck.ing&utm_medium=acknowledgement&utm_campaign=footer' },
{ name: 'RapidProxy', link: 'https://www.rapidproxy.io/?ref=myip' },
{ name: 'Sentry', link: 'https://www.sentry.io/' },
{ name: '1Password', link: 'https://www.1password.com/' },
{ name: 'Greptile', link: 'https://www.greptile.com/' },
Expand Down
6 changes: 3 additions & 3 deletions frontend/components/IpInfos.vue
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,12 @@ const trackFetchStatus = (status) => {
isp: card.isp,
// IPCheck.ing-source enrichments (locale-free codes; absent on other
// sources or when the field is sign-in-gated).
proxyCode: card.proxyCode,
anonymityCode: card.anonymityCode,
ipTypeCode: card.ipTypeCode,
isNativeIP: card.isNativeIP,
qualityScore: card.qualityScore,
proxyProtocol: card.proxyProtocol,
proxyProvider: card.proxyProvider,
anonymityProtocol: card.anonymityProtocol,
anonymityProvider: card.anonymityProvider,
})),
});
}
Expand Down
20 changes: 10 additions & 10 deletions frontend/components/User.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@
</section>
</TabsContent>

<!-- Usage tab: current-month usage vs quota per advanced feature.
Refetched on dialog open so the numbers are fresh. -->
<!-- Usage tab: share of the monthly quota used per advanced
feature — percentages only, the backend never sends raw
counts. Refetched on dialog open so the numbers are fresh. -->
<TabsContent value="usage" class="space-y-4 pt-3">
<div v-if="!isSignedIn"
class="flex items-start gap-2 p-3 rounded-md border border-info/30 bg-info/10 text-sm text-info">
Expand All @@ -75,7 +76,7 @@
<div class="flex items-baseline justify-between gap-2 text-sm">
<span>{{ t(row.labelKey) }}</span>
<span class="font-mono tabular-nums text-muted-foreground">
{{ row.used }} / {{ row.limit }}
{{ t('user.Usage.PercentUsed', { percent: row.percent }) }}
</span>
</div>
<Progress :model-value="row.percent" class="h-1.5"
Expand Down Expand Up @@ -141,9 +142,9 @@ const isOpen = ref(false);
const activeTab = ref('benefits');

// Three user tiers shown on the Benefits tab. `count` = number of ItemN keys
// in the locale pack; `current` badges the visitor's own tier (sponsor is
// detected from the quota multiplier the backend reports).
const isSponsor = computed(() => (remoteUserInfo.value?.quota?.multiplier ?? 1) > 1);
// in the locale pack; `current` badges the visitor's own tier (sponsor status
// comes from the backend's quota snapshot).
const isSponsor = computed(() => remoteUserInfo.value?.quota?.isSponsor === true);
const benefitTiers = computed(() => [
{ key: 'Visitor', icon: UserRound, count: 6, current: !isSignedIn.value },
{ key: 'SignedIn', icon: UserRoundCheck, count: 7, current: isSignedIn.value && !isSponsor.value },
Expand Down Expand Up @@ -174,10 +175,9 @@ const USAGE_LABEL_KEYS = {
const usageRows = computed(() => {
const features = remoteUserInfo.value?.quota?.features;
if (!features) return [];
return Object.entries(features).map(([key, { used, limit }]) => {
const percent = limit > 0 ? Math.min(100, Math.round((used / limit) * 100)) : 0;
const tone = percent >= 100 ? 'fail' : percent >= 80 ? 'ok-slow' : 'ok-fast';
return { key, labelKey: USAGE_LABEL_KEYS[key] || key, used, limit, percent, tone };
return Object.entries(features).map(([key, { percent, exhausted }]) => {
const tone = exhausted ? 'fail' : percent >= 80 ? 'ok-slow' : 'ok-fast';
return { key, labelKey: USAGE_LABEL_KEYS[key] || key, percent, tone };
});
});

Expand Down
Loading
Loading