feat(更新功能): 兼容metowolf提供的qqwry.ipdb格式(原版)

This commit is contained in:
2025-01-07 15:52:22 +08:00
parent 672ffb4f51
commit 13ade58f06
9 changed files with 63 additions and 8 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
.vscode/ .vscode/
.devcontainer/ .devcontainer/
assets/qqwry.dat assets/qqwry.dat
assets/qqwry.ipdb

View File

@@ -39,7 +39,8 @@ func main() {
# IP数据库 # IP数据库
- [https://aite.xyz/share-file/qqwry/qqwry.dat](https://aite.xyz/share-file/qqwry/qqwry.dat) - DAT格式[https://aite.xyz/share-file/qqwry/qqwry.dat](https://aite.xyz/share-file/qqwry/qqwry.dat)
- IPDB格式[https://aite.xyz/share-file/qqwry/qqwry.ipdb](https://aite.xyz/share-file/qqwry/qqwry.ipdb)
# 编译说明 # 编译说明
@@ -47,6 +48,11 @@ func main() {
2. client和server需要go1.16的内嵌资源特性。 2. client和server需要go1.16的内嵌资源特性。
3. 作为库使用请直接引包并不需要go1.16+才能编译。 3. 作为库使用请直接引包并不需要go1.16+才能编译。
# 数据更新
- 由于qqwry.dat缺乏更新官方czdb格式又难以获得和分发建议使用ipdb格式。
- 这里的ipdb格式指metowolf提供的官方czdb格式转换而来的ipdb格式纯真格式原版
# 服务接口 # 服务接口
1. 自行根据需要调整server下源码。 1. 自行根据需要调整server下源码。
@@ -57,6 +63,7 @@ func main() {
- 感谢[纯真IP库](https://www.cz88.net/)一直坚持为大家提供免费IP数据库。 - 感谢[纯真IP库](https://www.cz88.net/)一直坚持为大家提供免费IP数据库。
- 感谢[yinheli](https://github.com/yinheli)的[qqwry](https://github.com/yinheli/qqwry)项目为我提供纯真ip库解析算法参考。 - 感谢[yinheli](https://github.com/yinheli)的[qqwry](https://github.com/yinheli/qqwry)项目为我提供纯真ip库解析算法参考。
- 感谢[metowolf](https://github.com/metowolf)的[qqwry.ipdb](https://github.com/metowolf/qqwry.ipdb)项目提供纯真czdb转ipdb数据库。
# 授权说明 # 授权说明

View File

@@ -4,3 +4,6 @@ import _ "embed"
//go:embed qqwry.dat //go:embed qqwry.dat
var QQWryDat []byte var QQWryDat []byte
//go:embed qqwry.ipdb
var QQWryIpdb []byte

View File

@@ -8,7 +8,7 @@ import (
) )
func init() { func init() {
qqwry.LoadData(assets.QQWryDat) qqwry.LoadData(assets.QQWryIpdb)
} }
func main() { func main() {

2
go.mod
View File

@@ -3,3 +3,5 @@ module github.com/xiaoqidun/qqwry
go 1.20 go 1.20
require golang.org/x/text v0.21.0 require golang.org/x/text v0.21.0
require github.com/ipipdotnet/ipdb-go v1.3.3

2
go.sum
View File

@@ -1,2 +1,4 @@
github.com/ipipdotnet/ipdb-go v1.3.3 h1:GLSAW9ypLUd6EF9QNK2Uhxew9Jzs4XMJ9gOZEFnJm7U=
github.com/ipipdotnet/ipdb-go v1.3.3/go.mod h1:yZ+8puwe3R37a/3qRftXo40nZVQbxYDLqls9o5foexs=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=

View File

@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"errors" "errors"
"github.com/ipipdotnet/ipdb-go"
"golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform" "golang.org/x/text/transform"
"io" "io"
@@ -16,9 +17,16 @@ import (
var ( var (
data []byte data []byte
dataLen uint32 dataLen uint32
ipdbCity *ipdb.City
dataType = dataTypeDat
locationCache = &sync.Map{} locationCache = &sync.Map{}
) )
const (
dataTypeDat = 0
dataTypeIpdb = 1
)
const ( const (
indexLen = 7 indexLen = 7
redirectMode1 = 0x01 redirectMode1 = 0x01
@@ -49,10 +57,22 @@ func gb18030Decode(src []byte) string {
} }
// QueryIP 从内存或缓存查询IP // QueryIP 从内存或缓存查询IP
func QueryIP(ipv4 string) (location *Location, err error) { func QueryIP(ip string) (location *Location, err error) {
if v, ok := locationCache.Load(ipv4); ok { if v, ok := locationCache.Load(ip); ok {
return v.(*Location), nil return v.(*Location), nil
} }
switch dataType {
case dataTypeDat:
return QueryIPDat(ip)
case dataTypeIpdb:
return QueryIPIpdb(ip)
default:
return nil, errors.New("data type not support")
}
}
// QueryIPDat 从dat查询IP仅加载dat格式数据库时使用
func QueryIPDat(ipv4 string) (location *Location, err error) {
ip := net.ParseIP(ipv4).To4() ip := net.ParseIP(ipv4).To4()
if ip == nil { if ip == nil {
return nil, errors.New("ip is not ipv4") return nil, errors.New("ip is not ipv4")
@@ -156,19 +176,39 @@ func QueryIP(ipv4 string) (location *Location, err error) {
return location, nil return location, nil
} }
// QueryIPIpdb 从ipdb查询IP仅加载ipdb格式数据库时使用
func QueryIPIpdb(ip string) (location *Location, err error) {
ret, err := ipdbCity.Find(ip, "CN")
if err != nil {
return
}
location = SplitResult(ret[0], ret[1], ip)
locationCache.Store(ip, location)
return location, nil
}
// LoadData 从内存加载IP数据库 // LoadData 从内存加载IP数据库
func LoadData(database []byte) { func LoadData(database []byte) {
if string(database[6:11]) == "build" {
dataType = dataTypeIpdb
loadCity, err := ipdb.NewCityFromBytes(database)
if err != nil {
panic(err)
}
ipdbCity = loadCity
return
}
data = database data = database
dataLen = uint32(len(data)) dataLen = uint32(len(data))
} }
// LoadFile 从文件加载IP数据库 // LoadFile 从文件加载IP数据库
func LoadFile(filepath string) (err error) { func LoadFile(filepath string) (err error) {
data, err = os.ReadFile(filepath) body, err := os.ReadFile(filepath)
if err != nil { if err != nil {
return return
} }
dataLen = uint32(len(data)) LoadData(body)
return return
} }

View File

@@ -5,7 +5,7 @@ import (
) )
func init() { func init() {
if err := LoadFile("assets/qqwry.dat"); err != nil { if err := LoadFile("assets/qqwry.ipdb"); err != nil {
panic(err) panic(err)
} }
} }

View File

@@ -16,7 +16,7 @@ type resp struct {
} }
func init() { func init() {
qqwry.LoadData(assets.QQWryDat) qqwry.LoadData(assets.QQWryIpdb)
} }
func main() { func main() {