FastGPT/packages/service/common/geo/index.ts
Archer 2da73a6555
Some checks failed
Build FastGPT images in Personal warehouse / get-vars (push) Waiting to run
Build FastGPT images in Personal warehouse / build-fastgpt-images (map[arch:amd64 runs-on:ubuntu-24.04]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / build-fastgpt-images (map[arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / release-fastgpt-images (push) Blocked by required conditions
Document deploy / sync-images (push) Has been cancelled
Document deploy / generate-timestamp (push) Has been cancelled
Document deploy / build-images (map[domain:https://fastgpt.cn suffix:cn]) (push) Has been cancelled
Document deploy / build-images (map[domain:https://fastgpt.io suffix:io]) (push) Has been cancelled
Document deploy / update-images (map[deployment:fastgpt-docs domain:https://fastgpt.cn kube_config:KUBE_CONFIG_CN suffix:cn]) (push) Has been cancelled
Document deploy / update-images (map[deployment:fastgpt-docs domain:https://fastgpt.io kube_config:KUBE_CONFIG_IO suffix:io]) (push) Has been cancelled
V4.14.4 features (#6075)
* perf: faq

* index

* delete dataset

* delete dataset

* perf: delete dataset

* init

* fix: faq

* refresh

* empty tip

* perf: delete type

* fix: some bugs (#6071)

* fix: publish channel doc link

* fix: checkbox disable hover style

* fix: huggingface.svg missing; update doc

* chore: update doc

* fix: typo

* fix: export log dateend;feat: file selector render (#6072)

* fix: export log dateend

* feat: file selector render

* perf: s3 controller

* team qpm limit & plan tracks (#6066)

* team qpm limit & plan tracks

* api entry qpm

* perf: computed days

* Revert "api entry qpm"

This reverts commit 1210c07217.

* perf: code

* system qpm limit

* system qpm limit

---------

Co-authored-by: archer <545436317@qq.com>

* perf: track

* remove export chat test

* doc

* feat: global agent (#6057)

* feat: global agent

* fix: agent

* fix: order display

* CHORE

* feat: error page log

* fix: var update

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: Roy <whoeverimf5@gmail.com>
2025-12-10 20:07:05 +08:00

112 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'node:fs';
import type { ReaderModel } from '@maxmind/geoip2-node';
import { Reader } from '@maxmind/geoip2-node';
import { cleanupIntervalMs, dbPath, privateOrOtherLocationName } from './constants';
import type { LocationName } from './type';
import { extractLocationData } from './utils';
import type { NextApiRequest } from 'next';
import { getClientIp } from 'request-ip';
import { addLog } from '../system/log';
import type { localeType } from '@fastgpt/global/common/i18n/type';
import { formatI18nLocationToZhEn } from '@fastgpt/global/common/i18n/utils';
let reader: ReaderModel | null = null;
const locationIpMap = new Map<string, LocationName>();
function loadGeoDB() {
const dbBuffer = fs.readFileSync(dbPath);
reader = Reader.openBuffer(dbBuffer);
return reader;
}
export function getGeoReader() {
if (!reader) {
return loadGeoDB();
}
return reader;
}
export function getLocationFromIp(ip?: string, locale: localeType = 'zh-CN') {
const formatedLocale = formatI18nLocationToZhEn(locale);
if (!ip) {
return privateOrOtherLocationName.country?.[formatedLocale];
}
const reader = getGeoReader();
let locationName = locationIpMap.get(ip);
if (locationName) {
return [
locationName.country?.[formatedLocale],
locationName.province?.[formatedLocale],
locationName.city?.[formatedLocale]
]
.filter(Boolean)
.join(formatedLocale === 'zh' ? '' : ',');
}
try {
const response = reader.city(ip);
const data = extractLocationData(response);
locationName = {
city: {
en: data.city.en,
zh: data.city.zh
},
country: {
en: data.country.en,
zh: data.country.zh
},
province: {
en: data.province.en,
zh: data.province.zh
}
};
locationIpMap.set(ip, locationName);
return [
locationName.country?.[formatedLocale],
locationName.province?.[formatedLocale],
locationName.city?.[formatedLocale]
]
.filter(Boolean)
.join(formatedLocale === 'zh' ? '' : ', ');
} catch (error) {
locationIpMap.set(ip, privateOrOtherLocationName);
return privateOrOtherLocationName.country?.[formatedLocale];
}
}
let cleanupInterval: NodeJS.Timeout | null = null;
function cleanupIpMap() {
locationIpMap.clear();
}
export function clearCleanupInterval() {
if (cleanupInterval) {
clearInterval(cleanupInterval);
cleanupInterval = null;
}
}
export function initGeo() {
cleanupInterval = setInterval(cleanupIpMap, cleanupIntervalMs);
try {
loadGeoDB();
} catch (error) {
clearCleanupInterval();
addLog.error(`Failed to load geo db`, error);
throw error;
}
}
export function getIpFromRequest(request: NextApiRequest): string {
const ip = getClientIp(request);
if (!ip || ip === '::1') {
return '127.0.0.1';
}
return ip;
}