UNPKG

@blocklet/ui-react

Version:

Some useful front-end web components that can be used in Blocklets.

83 lines (75 loc) 2.17 kB
const RESERVED_IP = 'Reserved IP'; const IP_REGION_CACHE = 'ip-region-cache'; async function getIpRegionFromIpApi(ip: string): Promise<string> { const url = `https://ipapi.co/${ip}/json/`; const result = await fetch(url); const data = await result.json(); let region = ''; if (data.error) { if (data.reserved) { region = RESERVED_IP; } } else { region = [data.country_name, data.region, data.city].filter(Boolean).join('/'); } return region; } async function getIpRegionFromIpSb(ip: string): Promise<string> { const url = `https://api.ip.sb/geoip/${ip}`; const result = await fetch(url); const data = await result.json(); let region = ''; if (data.error) { if (data.reserved) { region = RESERVED_IP; } } else { region = [data.country, data.region, data.city].filter(Boolean).join('/'); } return region; } export async function ip2Region(ip: string): Promise<string> { let region = ''; let ipRegionCache: Record<string, string> = {}; try { const tmpCache = localStorage.getItem(IP_REGION_CACHE); if (tmpCache) { ipRegionCache = JSON.parse(tmpCache); } } catch { ipRegionCache = {}; } if (ipRegionCache[ip]) { region = ipRegionCache[ip]; } else { try { region = await getIpRegionFromIpSb(ip); } catch { console.warn('Fail to get ip region from ip.sb'); } if (!region) { try { region = await getIpRegionFromIpApi(ip); } catch { console.warn('Fail to get ip region from ip-api.co'); } } } if (region) { // NOTICE: 为了防止 cache 过大,将在 size 超过 100 时,删除最旧的数据 const ipList = Object.keys(ipRegionCache); if (ipList.length > 100) { delete ipRegionCache[ipList[0]]; } if (ipRegionCache[ip]) { delete ipRegionCache[ip]; } ipRegionCache[ip] = region; localStorage.setItem(IP_REGION_CACHE, JSON.stringify(ipRegionCache)); } return region; } // eslint-disable-next-line require-await export async function batchIp2Region(ips: string[]): Promise<string[]> { return Promise.all(ips.map((ip) => ip2Region(ip))); }