mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-11-16 14:13:46 +08:00
tt
This commit is contained in:
254
hotgo-server/app/com/ip_com.go
Normal file
254
hotgo-server/app/com/ip_com.go
Normal file
@@ -0,0 +1,254 @@
|
||||
//
|
||||
// @Link https://github.com/bufanyun/hotgo
|
||||
// @Copyright Copyright (c) 2022 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
//
|
||||
package com
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/axgle/mahonia"
|
||||
"github.com/bufanyun/hotgo/app/model/entity"
|
||||
"github.com/bufanyun/hotgo/app/utils"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/kayon/iploc"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Ip = new(ip)
|
||||
|
||||
type ip struct{}
|
||||
|
||||
type IpLocationData struct {
|
||||
Ip string `json:"ip"`
|
||||
Country string `json:"country"`
|
||||
Region string `json:"region"`
|
||||
Province string `json:"province"`
|
||||
ProvinceCode int `json:"province_code"`
|
||||
City string `json:"city"`
|
||||
CityCode int `json:"city_code"`
|
||||
Area string `json:"area"`
|
||||
AreaCode int `json:"area_code"`
|
||||
}
|
||||
|
||||
//
|
||||
// @Title 通过Whois接口查询IP归属地
|
||||
// @Description
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @Param ctx
|
||||
// @Param ip
|
||||
// @Return IpLocationData
|
||||
//
|
||||
func (component *ip) WhoisLocation(ctx context.Context, ip string) IpLocationData {
|
||||
|
||||
type whoisRegionData struct {
|
||||
Ip string `json:"ip"`
|
||||
Pro string `json:"pro" `
|
||||
ProCode string `json:"proCode" `
|
||||
City string `json:"city" `
|
||||
CityCode string `json:"cityCode"`
|
||||
Region string `json:"region"`
|
||||
RegionCode string `json:"regionCode"`
|
||||
Addr string `json:"addr"`
|
||||
Err string `json:"err"`
|
||||
}
|
||||
|
||||
if !utils.Validate.IsIp(ip) {
|
||||
return IpLocationData{}
|
||||
}
|
||||
|
||||
response, err := g.Client().Timeout(10*time.Second).Get(ctx, "http://whois.pconline.com.cn/ipJson.jsp?ip="+ip+"&json=true")
|
||||
if err != nil {
|
||||
err = gerror.New(err.Error())
|
||||
return IpLocationData{
|
||||
Ip: ip,
|
||||
}
|
||||
}
|
||||
|
||||
defer response.Close()
|
||||
|
||||
var enc mahonia.Decoder
|
||||
enc = mahonia.NewDecoder("gbk")
|
||||
|
||||
data := enc.ConvertString(response.ReadAllString())
|
||||
|
||||
g.Log().Print(ctx, "data:", data)
|
||||
whoisData := whoisRegionData{}
|
||||
if err := gconv.Struct(data, &whoisData); err != nil {
|
||||
err = gerror.New(err.Error())
|
||||
|
||||
g.Log().Print(ctx, "err:", err)
|
||||
return IpLocationData{
|
||||
Ip: ip,
|
||||
}
|
||||
}
|
||||
|
||||
g.Log().Print(ctx, "whoisData:", whoisData)
|
||||
|
||||
return IpLocationData{
|
||||
Ip: whoisData.Ip,
|
||||
//Country string `json:"country"`
|
||||
Region: whoisData.Addr,
|
||||
Province: whoisData.Pro,
|
||||
ProvinceCode: gconv.Int(whoisData.ProCode),
|
||||
City: whoisData.City,
|
||||
CityCode: gconv.Int(whoisData.CityCode),
|
||||
Area: whoisData.Region,
|
||||
AreaCode: gconv.Int(whoisData.RegionCode),
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// @Title 通过Cz88的IP库查询IP归属地
|
||||
// @Description
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @Param ctx
|
||||
// @Param ip
|
||||
// @Return IpLocationData
|
||||
//
|
||||
func (component *ip) Cz88Find(ctx context.Context, ip string) IpLocationData {
|
||||
if !utils.Validate.IsIp(ip) {
|
||||
g.Log().Print(ctx, "ip格式错误:", ip)
|
||||
return IpLocationData{}
|
||||
}
|
||||
|
||||
loc, err := iploc.OpenWithoutIndexes("./storage/ip/qqwry-utf8.dat")
|
||||
if err != nil {
|
||||
err = gerror.New(err.Error())
|
||||
return IpLocationData{
|
||||
Ip: ip,
|
||||
}
|
||||
}
|
||||
|
||||
detail := loc.Find(ip)
|
||||
if detail == nil {
|
||||
return IpLocationData{
|
||||
Ip: ip,
|
||||
}
|
||||
}
|
||||
|
||||
locationData := IpLocationData{
|
||||
Ip: ip,
|
||||
Country: detail.Country,
|
||||
Region: detail.Region,
|
||||
Province: detail.Province,
|
||||
City: detail.City,
|
||||
Area: detail.County,
|
||||
}
|
||||
|
||||
if gstr.LenRune(locationData.Province) == 0 {
|
||||
return locationData
|
||||
}
|
||||
|
||||
var (
|
||||
provinceModel *entity.SysProvinces
|
||||
cityModel *entity.SysProvinces
|
||||
areaModel *entity.SysProvinces
|
||||
)
|
||||
|
||||
err = g.DB().Model("hg_common_provinces").
|
||||
Where("level", 1).
|
||||
WhereLike("title", "%"+locationData.Province+"%").
|
||||
Scan(&provinceModel)
|
||||
|
||||
if err != nil {
|
||||
err = gerror.New(err.Error())
|
||||
return locationData
|
||||
}
|
||||
|
||||
if provinceModel != nil {
|
||||
locationData.ProvinceCode = provinceModel.Id
|
||||
locationData.Province = provinceModel.Title
|
||||
}
|
||||
|
||||
if gstr.LenRune(locationData.City) == 0 {
|
||||
return locationData
|
||||
|
||||
// 是否为直辖市
|
||||
} else if component.IsJurisdictionByIpTitle(locationData.City) {
|
||||
locationData.CityCode = provinceModel.Id + 100
|
||||
locationData.City = "直辖市"
|
||||
} else {
|
||||
|
||||
//替换掉
|
||||
locationData.City = gstr.Replace(locationData.City, "地区", "")
|
||||
|
||||
err = g.DB().Model("hg_common_provinces").
|
||||
Where("level", 2).
|
||||
Where("pid", locationData.ProvinceCode).
|
||||
WhereLike("title", "%"+locationData.City+"%").
|
||||
Scan(&cityModel)
|
||||
|
||||
if err != nil {
|
||||
err = gerror.New(err.Error())
|
||||
return locationData
|
||||
}
|
||||
|
||||
if cityModel != nil {
|
||||
locationData.CityCode = cityModel.Id
|
||||
locationData.City = cityModel.Title
|
||||
}
|
||||
}
|
||||
|
||||
if gstr.LenRune(locationData.Area) == 0 {
|
||||
return locationData
|
||||
}
|
||||
|
||||
err = g.DB().Model("hg_common_provinces").
|
||||
Where("level", 3).
|
||||
Where("pid", locationData.CityCode).
|
||||
WhereLike("title", "%"+locationData.Area+"%").
|
||||
Scan(&areaModel)
|
||||
|
||||
if err != nil {
|
||||
err = gerror.New(err.Error())
|
||||
return locationData
|
||||
}
|
||||
|
||||
if areaModel != nil {
|
||||
locationData.AreaCode = areaModel.Id
|
||||
locationData.Area = areaModel.Title
|
||||
}
|
||||
|
||||
return locationData
|
||||
}
|
||||
|
||||
//
|
||||
// @Title 判断地区名称是否为直辖市
|
||||
// @Description
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @Param title
|
||||
// @Return bool
|
||||
//
|
||||
func (component *ip) IsJurisdictionByIpTitle(title string) bool {
|
||||
|
||||
lists := []string{"北京市", "天津市", "重庆市", "上海市"}
|
||||
|
||||
for i := 0; i < len(lists); i++ {
|
||||
if gstr.Contains(lists[i], title) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//
|
||||
// @Title 获取IP归属地信息
|
||||
// @Description
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @Param ctx
|
||||
// @Param ip
|
||||
// @Return IpLocationData
|
||||
//
|
||||
func (component *ip) GetLocation(ctx context.Context, ip string) IpLocationData {
|
||||
method, _ := g.Cfg().Get(ctx, "hotgo.ipMethod", "cz88")
|
||||
|
||||
if method.String() == "whois" {
|
||||
return component.WhoisLocation(ctx, ip)
|
||||
}
|
||||
return component.Cz88Find(ctx, ip)
|
||||
}
|
||||
Reference in New Issue
Block a user