mirror of
https://github.com/xiaoqidun/qqwry.git
synced 2025-12-09 01:12:55 +08:00
feat(更新功能): 兼容metowolf提供的qqwry.ipdb格式(原版)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
.devcontainer/
|
.devcontainer/
|
||||||
assets/qqwry.dat
|
assets/qqwry.dat
|
||||||
|
assets/qqwry.ipdb
|
||||||
@@ -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数据库。
|
||||||
|
|
||||||
# 授权说明
|
# 授权说明
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
qqwry.LoadData(assets.QQWryDat)
|
qqwry.LoadData(assets.QQWryIpdb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -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
2
go.sum
@@ -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=
|
||||||
|
|||||||
48
qqwry.go
48
qqwry.go
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type resp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
qqwry.LoadData(assets.QQWryDat)
|
qqwry.LoadData(assets.QQWryIpdb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
Reference in New Issue
Block a user