feat: geo ip.

This commit is contained in:
tx7do
2023-10-19 15:27:32 +08:00
parent 01bdf5cc06
commit 7965576c1c
8 changed files with 73 additions and 34 deletions

15
geoip/geoip.go Normal file
View File

@@ -0,0 +1,15 @@
package geoip
// Result 归属地信息
type Result struct {
IP string `json:"ip"`
Country string `json:"country"` // 国家
Province string `json:"province"` // 省
City string `json:"city"` // 城市
ISP string `json:"isp"` // 服务提供商
}
// GeoIP 客户端
type GeoIP interface {
Query(queryIp string) (res Result, err error)
}

1
geoip/geoip_test.go Normal file
View File

@@ -0,0 +1 @@
package geoip

View File

@@ -6,15 +6,11 @@ import (
"github.com/go-kratos/kratos/v2/log"
"github.com/oschwald/geoip2-golang"
"github.com/tx7do/kratos-utils/geoip"
"github.com/tx7do/kratos-utils/geoip/geolite/assets"
)
type Result struct {
Country string // 国家
Province string // 省
City string // 城市
}
const defaultOutputLanguage = "zh-CN"
// Client 地理位置解析结构体
@@ -56,7 +52,7 @@ func (g *Client) query(rawIP string) (city *geoip2.City, err error) {
}
// Query 通过IP获取地区
func (g *Client) Query(rawIP string) (ret Result, err error) {
func (g *Client) Query(rawIP string) (ret geoip.Result, err error) {
record, err := g.query(rawIP)
if err != nil {
log.Fatal(err)

View File

@@ -7,14 +7,3 @@ const (
redirectMode2 = 0x02 // RedirectMode2 国家的类型, 指向一个指向
)
//var unCountry = []byte{"未知国家"}
//var unArea = []byte{"未知地区"}
// Result 归属地信息
type Result struct {
IP string `json:"ip"`
Country string `json:"country"`
Area string `json:"area"`
ISP string `json:"isp"`
}

View File

@@ -3,6 +3,7 @@ package qqwry
import (
"encoding/binary"
"errors"
"github.com/tx7do/kratos-utils/geoip"
"net"
"strings"
"sync"
@@ -136,7 +137,10 @@ func (c *Client) readUInt24(offset int32) uint32 {
return i
}
func (c *Client) Query(queryIp string) (country, city, isp string, err error) {
func (c *Client) Query(queryIp string) (res geoip.Result, err error) {
res.IP = queryIp
res.Country = "中国"
ip32, err := c.parseIp(queryIp)
if err != nil {
return
@@ -152,7 +156,8 @@ func (c *Client) Query(queryIp string) (country, city, isp string, err error) {
offset += 4
mode := c.readMode(uint32(offset))
var _city []byte
var _area []byte
var area string
var ispPos uint32
switch mode {
@@ -164,25 +169,35 @@ func (c *Client) Query(queryIp string) (country, city, isp string, err error) {
posCA = c.readUInt24(int32(posC) + 1)
posC += 4
}
_city = c.readString(posCA)
_area = c.readString(posCA)
if mode != redirectMode2 {
posC += uint32(len(city) + 1)
posC += uint32(len(area) + 1)
}
ispPos = posC
case redirectMode2:
posCA := c.readUInt24(offset + 1)
_city = c.readString(posCA)
_area = c.readString(posCA)
ispPos = uint32(offset) + 4
default:
posCA := offset + 0
_city = c.readString(uint32(posCA))
ispPos = uint32(offset) + uint32(len(city)) + 1
_area = c.readString(uint32(posCA))
ispPos = uint32(offset) + uint32(len(area)) + 1
}
if len(_city) != 0 {
city = strings.TrimSpace(gb18030Decode(_city))
if len(_area) != 0 {
area = strings.TrimSpace(gb18030Decode(_area))
areas := SpiltAddress(area)
if len(areas) == 2 {
res.Province = areas[0]
res.City = areas[1]
} else if len(areas) == 1 {
res.City = areas[0]
} else {
res.City = area
}
}
ispMode := assets.QQWryDat[ispPos]
@@ -192,10 +207,10 @@ func (c *Client) Query(queryIp string) (country, city, isp string, err error) {
if ispPos > 0 {
var _isp []byte
_isp = c.readString(ispPos)
isp = strings.TrimSpace(gb18030Decode(_isp))
if isp != "" {
if strings.Contains(isp, "CZ88.NET") {
isp = ""
res.ISP = strings.TrimSpace(gb18030Decode(_isp))
if res.ISP != "" {
if strings.Contains(res.ISP, "CZ88.NET") {
res.ISP = ""
}
}
}

View File

@@ -2,15 +2,20 @@ package qqwry
import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestClient(t *testing.T) {
g := NewClient()
assert.NotNil(t, g)
country, city, isp, err := g.Query("47.108.149.89")
res, err := g.Query("47.108.149.89")
assert.Nil(t, err)
fmt.Println("国家:", country, "城市:", city, "服务商:", isp)
fmt.Println("国家:", res.Country, "省:", res.Province, "城市:", res.City, "服务商:", res.ISP)
assert.Equal(t, res.Country, "中国")
assert.Equal(t, res.Province, "四川省")
assert.Equal(t, res.City, "成都市")
assert.Equal(t, res.ISP, "阿里云")
}

View File

@@ -3,11 +3,14 @@ package qqwry
import (
"bytes"
"io"
"regexp"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
var regSpiltAddress = regexp.MustCompile(`.+?(省|市|自治区|自治州|盟|县|区|管委会|街道|镇|乡)`)
func gb18030Decode(src []byte) string {
in := bytes.NewReader(src)
out := transform.NewReader(in, simplifiedchinese.GB18030.NewDecoder())
@@ -26,3 +29,7 @@ func byte3ToUInt32(data []byte) uint32 {
i |= (uint32(data[2]) << 16) & 0xff0000
return i
}
func SpiltAddress(addr string) []string {
return regSpiltAddress.FindAllString(addr, -1)
}

11
geoip/qqwry/utils_test.go Normal file
View File

@@ -0,0 +1,11 @@
package qqwry
import (
"fmt"
"testing"
)
func TestSpiltAddress(t *testing.T) {
names := SpiltAddress("浙江省杭州市西湖区")
fmt.Println(names)
}