Files
mihomo-patchbay/shared/geo.ts
T
im0o b276c4a8fe 轻提示铺开到全部页面;内核状态悬停变重启;GEO 支持单文件下载
侧栏动作排撤掉重启图标,内核状态(圆点加版本号)本身变成按钮:悬停
换层显示「重启内核」,不在线时只当状态看。行高压成 1 修掉圆点和等宽
字体不居中的问题。

四个页面的一次性反馈(保存、删除、更新订阅、断开连接、测延迟结论)
全部改走 toast,commit() 改返回成败给「失败不关对话框」用;持续状态
(连接页轮询失败、请求页日志流失败)留在页内,会自动消失的提示装不下
需要一直可见的信息。toast 加 info 类别给中性结论用。

GEO 每行的更新改成单独下载那一个文件:内核只有全量更新的口子,单文件
只能服务端自己下(POST /api/geo/sync),代价是只有形状校验(MaxMind
末尾标记、geodata 首字节,shared/geo.ts 带测试)且内核重启后才换用新
文件;「更新全部」文字按钮保留内核的全量口子,有完整校验和热加载。
上传两行的按钮改「选择或拖放文件」,投放区拖入高亮,恢复策略挪到
恢复行下方。
2026-08-12 02:20:46 +08:00

65 lines
2.7 KiB
TypeScript
Raw Permalink 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.
/**
* GEO 数据库的四类文件。名字和默认下载地址都来自内核源码,
* 界面(资源一节)和服务端(查文件大小和时间)共用这一份。
*/
export interface GeoFileStatus {
/** 界面上显示的名字 */
key: string
/** 在配置 geox-url 段落里的键名(config.go:363-368) */
configKey: string
/** 下载地址:配置里写了用配置的,没写是内核默认 */
url: string
/** 文件字节数。文件还没下载过是 null */
size: number | null
/** 文件修改时间,ISO 格式。没下载过是 null */
updatedAt: string | null
}
/**
* 文件名与内核一致(constant/path.go:18-20、144)。
* GeoIP.dat 和 GeoSite.dat 内核在目录里大小写不敏感地找(path.go:193-224),
* 服务端查文件时也要同样处理。
*/
export const GEO_FILES = [
{ key: 'MMDB', configKey: 'mmdb', file: 'geoip.metadb' },
{ key: 'ASN', configKey: 'asn', file: 'ASN.mmdb' },
{ key: 'GEOIP', configKey: 'geoip', file: 'GeoIP.dat' },
{ key: 'GEOSITE', configKey: 'geosite', file: 'GeoSite.dat' },
] as const
/**
* 下载内容的形状检查,挡住 HTML 错误页、截断的下载这类明显的坏文件。
* Patchbay 自己下载单个 GEO 文件时用(内核的更新接口是全量的,单文件
* 下载只能自己来,也就拿不到内核那套完整校验)。
*/
/** MaxMind 格式:元数据标记按规范出现在文件末尾 128KB 内。MMDB 和 ASN 都是这个格式。 */
export function looksLikeMmdb(bytes: Uint8Array): boolean {
const marker = [0xab, 0xcd, 0xef, ...Array.from('MaxMind.com', (c) => c.charCodeAt(0))]
const from = Math.max(0, bytes.length - 128 * 1024)
outer: for (let i = from; i <= bytes.length - marker.length; i++) {
for (let j = 0; j < marker.length; j++) {
if (bytes[i + j] !== marker[j]) continue outer
}
return true
}
return false
}
/**
* geoip.dat / geosite.dat:GeoIPList 和 GeoSiteList 都是「repeated 消息字段 1」,
* 首字节必然是 0x0a。弱校验,但足够挡住以 '<' 开头的错误页和空文件。
*/
export function looksLikeGeodata(bytes: Uint8Array): boolean {
return bytes.length > 1024 && bytes[0] === 0x0a
}
/** 内核的默认下载地址(config.go:578-583)。配置里没写 geox-url 时就是这些。 */
export const DEFAULT_GEOX_URLS: Record<string, string> = {
mmdb: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb',
asn: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb',
geoip: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat',
geosite: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
}