hotgo/hotgo-server/app/com/ip_com.go

256 lines
5.8 KiB
Go
Raw Normal View History

2022-02-25 17:11:17 +08:00
//
// @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"
)
// IP归属地
2022-02-25 17:11:17 +08:00
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)
}