mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-02-03 02:54:41 +08:00
198 lines
4.4 KiB
Go
198 lines
4.4 KiB
Go
// Package location
|
|
// @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 location
|
|
|
|
import (
|
|
"context"
|
|
"github.com/axgle/mahonia"
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/net/ghttp"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
"github.com/kayon/iploc"
|
|
"hotgo/utility/validate"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type IpLocationData struct {
|
|
Ip string `json:"ip"`
|
|
Country string `json:"country"`
|
|
Region string `json:"region"`
|
|
Province string `json:"province"`
|
|
ProvinceCode int64 `json:"province_code"`
|
|
City string `json:"city"`
|
|
CityCode int64 `json:"city_code"`
|
|
Area string `json:"area"`
|
|
AreaCode int64 `json:"area_code"`
|
|
}
|
|
|
|
// WhoisLocation 通过Whois接口查询IP归属地
|
|
func 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 !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())
|
|
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,
|
|
}
|
|
}
|
|
|
|
return IpLocationData{
|
|
Ip: whoisData.Ip,
|
|
//Country string `json:"country"`
|
|
Region: whoisData.Addr,
|
|
Province: whoisData.Pro,
|
|
ProvinceCode: gconv.Int64(whoisData.ProCode),
|
|
City: whoisData.City,
|
|
CityCode: gconv.Int64(whoisData.CityCode),
|
|
Area: whoisData.Region,
|
|
AreaCode: gconv.Int64(whoisData.RegionCode),
|
|
}
|
|
}
|
|
|
|
// Cz88Find 通过Cz88的IP库查询IP归属地
|
|
func Cz88Find(ctx context.Context, ip string) IpLocationData {
|
|
if !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
|
|
}
|
|
|
|
return locationData
|
|
}
|
|
|
|
// IsJurisByIpTitle 判断地区名称是否为直辖市
|
|
func IsJurisByIpTitle(title string) bool {
|
|
|
|
lists := []string{"北京市", "天津市", "重庆市", "上海市"}
|
|
|
|
for i := 0; i < len(lists); i++ {
|
|
if gstr.Contains(lists[i], title) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GetLocation 获取IP归属地信息
|
|
func GetLocation(ctx context.Context, ip string) IpLocationData {
|
|
method, _ := g.Cfg().Get(ctx, "hotgo.ipMethod", "cz88")
|
|
|
|
if method.String() == "whois" {
|
|
return WhoisLocation(ctx, ip)
|
|
}
|
|
return Cz88Find(ctx, ip)
|
|
}
|
|
|
|
// GetPublicIP 获取公网IP
|
|
func GetPublicIP() (ip string, err error) {
|
|
response, err := http.Get("http://members.3322.org/dyndns/getip")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
body, _ := ioutil.ReadAll(response.Body)
|
|
ip = string(body)
|
|
ip = strings.ReplaceAll(ip, "\n", "")
|
|
return
|
|
}
|
|
|
|
// GetLocalIP 获取服务器内网IP
|
|
func GetLocalIP() (ip string, err error) {
|
|
addrs, err := net.InterfaceAddrs()
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, addr := range addrs {
|
|
ipAddr, ok := addr.(*net.IPNet)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if ipAddr.IP.IsLoopback() {
|
|
continue
|
|
}
|
|
if !ipAddr.IP.IsGlobalUnicast() {
|
|
continue
|
|
}
|
|
return ipAddr.IP.String(), nil
|
|
}
|
|
return
|
|
}
|
|
|
|
// GetClientIp 获取客户端IP
|
|
func GetClientIp(r *ghttp.Request) string {
|
|
ip := r.Header.Get("X-Forwarded-For")
|
|
if ip == "" {
|
|
ip = r.GetClientIp()
|
|
}
|
|
return ip
|
|
}
|