diff --git a/common/rpc/rpc.go b/common/rpc/rpc.go index d703ffa47..735f239bc 100644 --- a/common/rpc/rpc.go +++ b/common/rpc/rpc.go @@ -86,7 +86,7 @@ func StartClient(id, port uint16, callback any) *struct { } { var rpcaddr, _ = service.NewBaseSysParamService().DataByKey(context.Background(), "server_ip") - //rpcaddr = "127.0.0.1" + rpcaddr = "127.0.0.1" closer1, err := jsonrpc.NewMergeClient(context.Background(), "ws://"+rpcaddr+":"+rpcport, "", []interface{}{ &RPCClient, diff --git a/common/utils/qqwry/qqwry.go b/common/utils/qqwry/qqwry.go index bb59d06a6..036215bcb 100644 --- a/common/utils/qqwry/qqwry.go +++ b/common/utils/qqwry/qqwry.go @@ -12,12 +12,9 @@ import ( "net/http" "net/url" "os" - "regexp" "strings" "sync" - _ "embed" - "github.com/ipipdotnet/ipdb-go" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/transform" @@ -88,143 +85,6 @@ func QueryIP(ip string) (location *Location, err error) { } } -// GetIpAddress 获取 IP 归属地和运营商 -func GetIpAddress(ip string) (string, error) { - html, err := doGet("https://www.ipshudi.com/" + ip + "/") - if err != nil { - return "", err - } - - div := getAddress(html, `\n.*\n`) - div1 := getAddress(html, `运营商.*`) - - location := "未知归属地" - if div != "" { - location = strings.Split(div, "")[1] - location = strings.Split(location, "")[0] - } - - isp := "" - if div1 != "" { - isp = strings.Split(div1, "")[1] - isp = strings.Split(isp, "")[0] - } - - return location + " " + isp, nil -} - -// 定义响应数据结构(与 API 返回字段对应) -type IPLocationResponse struct { - IP string `json:"ip"` - IPNumber string `json:"ip_number"` - IPVersion int `json:"ip_version"` - CountryName string `json:"country_name"` - CountryCode2 string `json:"country_code2"` - ISP string `json:"isp"` - ResponseCode string `json:"response_code"` - ResponseMessage string `json:"response_message"` -} - -// 调用 IP 定位 API -func LookupIP(ip string, format string) (*IPLocationResponse, error) { - // 构建请求 URL - baseURL := "https://api.iplocation.net/" - params := url.Values{} - params.Add("ip", ip) - if format != "" { - params.Add("format", format) - } - - fullURL := baseURL + "?" + params.Encode() - - // 发送 GET 请求 - resp, err := http.Get(fullURL) - if err != nil { - return nil, fmt.Errorf("请求失败: %v", err) - } - defer resp.Body.Close() - - // 读取响应体 - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("读取响应失败: %v", err) - } - - // 解析 JSON 响应(默认格式为 json) - var result IPLocationResponse - if err := json.Unmarshal(body, &result); err != nil { - return nil, fmt.Errorf("解析响应失败: %v (响应内容: %s)", err, string(body)) - } - - // 检查 API 响应状态 - if result.ResponseCode != "200" { - return nil, fmt.Errorf("API 调用失败: %s (%s)", result.ResponseMessage, result.ResponseCode) - } - - return &result, nil -} - -// doGet 发送 HTTP GET 请求,返回响应内容 -func doGet(url string) ([]byte, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - return body, nil -} - -// getAddress 使用正则表达式从 HTML 中提取内容 -func getAddress(html []byte, pattern string) string { - re := regexp.MustCompile(pattern) - return re.FindString(string(html)) -} - -// 判断IP是否为私有地址(包括IPv4和IPv6) -func isPrivateIP(ipStr string) (bool, error) { - ip := net.ParseIP(ipStr) - if ip == nil { - return false, fmt.Errorf("无效的IP地址: %s", ipStr) - } - - // 定义私有网段 - privateNets := []string{ - // IPv4私有网段 - "10.0.0.0/8", - "172.16.0.0/12", - "192.168.0.0/16", - // IPv6私有网段(ULA和链路本地) - "fc00::/7", - "fe80::/10", - } - - // 检查IP是否属于任一私有网段 - for _, cidr := range privateNets { - _, netIP, err := net.ParseCIDR(cidr) - if err != nil { - return false, err - } - if netIP.Contains(ip) { - return true, nil - } - } - return false, nil -} - -// 判断IP是否为环回地址 -func isLoopbackIP(ipStr string) (bool, error) { - ip := net.ParseIP(ipStr) - if ip == nil { - return false, fmt.Errorf("无效的IP地址: %s", ipStr) - } - return ip.IsLoopback(), nil -} - // QueryIPDat 从dat查询IP,仅加载dat格式数据库时使用 func QueryIPDat(ipv4 string) (location *Location, err error) { ip := net.ParseIP(ipv4).To4() @@ -232,11 +92,24 @@ func QueryIPDat(ipv4 string) (location *Location, err error) { return nil, errors.New("ip is not ipv4") } - if isLoopback, err := isLoopbackIP(ipv4); isLoopback || err != nil { + if ip.IsLoopback() { return &Location{ISP: "局域网", IP: ipv4}, nil } - if isPrivateIP, err := isPrivateIP(ipv4); isPrivateIP || err != nil { - return &Location{ISP: "私有地址", IP: ipv4}, nil + + privateNets := []string{ + "10.0.0.0/8", + "172.16.0.0/12", + "192.168.0.0/16", + } + + for _, cidr := range privateNets { + _, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + continue + } + if ipnet.Contains(ip) { + return &Location{ISP: "私有地址", IP: ipv4}, nil + } } ip32 := binary.BigEndian.Uint32(ip) posA := binary.LittleEndian.Uint32(data[:4]) @@ -245,16 +118,19 @@ func QueryIPDat(ipv4 string) (location *Location, err error) { for { mid := posA + (((posZ-posA)/indexLen)>>1)*indexLen if int(mid+indexLen) > len(data) { + // 当数据中找不到IP时,尝试使用网络查询 r, _ := LookupIP(ipv4, "json") if r != nil { - location := &Location{ISP: r.ISP, IP: r.IP, Country: r.CountryName, District: r.CountryCode2} - + location := &Location{ + IP: r.IP, + Country: r.CountryName, + ISP: r.ISP, + } locationCache.Store(ipv4, location) return location, nil } else { return nil, errors.New("ip not found") } - } buf := data[mid : mid+indexLen] _ip := binary.LittleEndian.Uint32(buf[:4]) @@ -360,6 +236,56 @@ func QueryIPIpdb(ip string) (location *Location, err error) { locationCache.Store(ip, location) return location, nil } +// IPLocationResponse 定义IP定位API的响应结构 +type IPLocationResponse struct { + IP string `json:"ip"` + IPNumber string `json:"ip_number"` + IPVersion int `json:"ip_version"` + CountryName string `json:"country_name"` + CountryCode2 string `json:"country_code2"` + ISP string `json:"isp"` + ResponseCode string `json:"response_code"` + ResponseMessage string `json:"response_message"` +} + +// LookupIP 调用外部API查询IP地理位置 +func LookupIP(ip string, format string) (*IPLocationResponse, error) { + // 构建请求 URL + baseURL := "https://api.iplocation.net/" + params := url.Values{} + params.Add("ip", ip) + if format != "" { + params.Add("format", format) + } + + fullURL := baseURL + "?" + params.Encode() + + // 发送 GET 请求 + resp, err := http.Get(fullURL) + if err != nil { + return nil, fmt.Errorf("请求失败: %v", err) + } + defer resp.Body.Close() + + // 读取响应体 + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("读取响应失败: %v", err) + } + + // 解析 JSON 响应 + var result IPLocationResponse + if err := json.Unmarshal(body, &result); err != nil { + return nil, fmt.Errorf("解析响应失败: %v (响应内容: %s)", err, string(body)) + } + + // 检查 API 响应状态 + if result.ResponseCode != "200" { + return nil, fmt.Errorf("API 调用失败: %s (%s)", result.ResponseMessage, result.ResponseCode) + } + + return &result, nil +} // LoadData 从内存加载IP数据库 func LoadData(database []byte) { @@ -407,3 +333,4 @@ func SplitResult(addr string, isp string, ipv4 string) (location *Location) { } return } + diff --git a/logic/server.go b/logic/server.go index 2d0af03ae..381624365 100644 --- a/logic/server.go +++ b/logic/server.go @@ -63,6 +63,7 @@ func Start() { } port, err := determinePort(cool.Config.ServerInfo.CanPort) + cool.Config.ServerInfo.Port = uint16(port) if err != nil { log.Fatalf("Failed to determine port: %v", err) } diff --git a/modules/base/service/base_sys_log.go b/modules/base/service/base_sys_log.go index 17adbe065..a98132220 100644 --- a/modules/base/service/base_sys_log.go +++ b/modules/base/service/base_sys_log.go @@ -2,6 +2,7 @@ package service import ( "blazing/cool" + "fmt" "sync" "blazing/modules/base/model" @@ -33,22 +34,38 @@ func NewBaseSysLogService() *BaseSysLogService { }, }, ModifyResult: func(ctx g.Ctx, data interface{}) interface{} { - // baseSysLog.IPAddr = fmt.Sprintf("国家:%s,省份:%s,城市:%s,区县:%s,运营商:%s\n", - // location.Country, - // location.Province, - // location.City, - // location.District, - // location.ISP, - // ) + + var rr []g.MapStrAny r, _ := gconv.Map(data)["list"].(gdb.Result) - for _, v := range r { - ipaddr, err := qqwry.QueryIP(v.Map()["ip"].(string)) + for i := 0; i < len(r); i++ { + subm := r[i].GMap() + ipaddr, err := qqwry.QueryIP(r[i].Map()["ip"].(string)) if err == nil { - v.GMap().Set("ipAddr", ipaddr) + // baseSysLog.IPAddr = fmt.Sprintf("国家:%s,省份:%s,城市:%s,区县:%s,运营商:%s\n", + // location.Country, + // location.Province, + // location.City, + // location.District, + // location.ISP, + // ) + + subm.Set("ipAddr", fmt.Sprintf("国家:%s,省份:%s,城市:%s,区县:%s,运营商:%s\n", + ipaddr.Country, + ipaddr.Province, + ipaddr.City, + ipaddr.District, + ipaddr.ISP, + )) + } + rr = append(rr, subm.MapStrAny()) } + + data.(map[string]interface{})["list"] = rr + return data + }, }, }, diff --git a/modules/blazing/service/item.go b/modules/blazing/service/item.go index 26f5568b2..cf1098ce8 100644 --- a/modules/blazing/service/item.go +++ b/modules/blazing/service/item.go @@ -38,7 +38,7 @@ func (s *ItemService) UPDATE(id uint32, count int) { "item_id": id, "item_cnt": count, } - data = cool.SetTest(data) + //data = cool.SetTest(data) m.Data(data).Insert() } diff --git a/modules/config/model/server_list.go b/modules/config/model/server_list.go index d6f1fb1f2..45bfec1a1 100644 --- a/modules/config/model/server_list.go +++ b/modules/config/model/server_list.go @@ -12,6 +12,8 @@ const TableNameServerList = "server_list" type ServerList struct { *cool.Model coolconfig.ServerList + //isonline + IsOnline uint8 `gorm:"column:isonline;default:0;comment:'是否在线'" json:"isonline"` } // TableName ServerList's table name diff --git a/modules/config/service/server.go b/modules/config/service/server.go index 94b04532f..f5caef738 100644 --- a/modules/config/service/server.go +++ b/modules/config/service/server.go @@ -29,24 +29,29 @@ func NewServerService() *ServerService { Model: model.NewServerList(), PageQueryOp: &cool.QueryOp{ ModifyResult: func(ctx g.Ctx, data interface{}) interface{} { - + var rr []g.MapStrAny r, _ := gconv.Map(data)["list"].(gdb.Result) - for _, v := range r { - t, ok := cool.GetClient(gconv.Uint16(v.Map()["port"])) + for i := 0; i < len(r); i++ { + t, ok := cool.GetClient(gconv.Uint16(r[i].Map()["port"])) + // tt.Friends = v.Friends + subm := r[i].GMap() if ok { cool.Logger.Info(context.TODO(), "服务器假踢人") err := t.KickPerson(0) //实现指定服务器踢人 if err == nil { - // tt.Friends = v.Friends - v.GMap().Set("isonline", 1) + + subm.Set("isonline", 1) } } - + rr = append(rr, subm.MapStrAny()) } + + data.(map[string]interface{})["list"] = rr + return data }, }, diff --git a/public/login-login-linux-amd64 b/public/login-login-linux-amd64 index 5b8e8a651..6d521297a 100644 Binary files a/public/login-login-linux-amd64 and b/public/login-login-linux-amd64 differ