parent
649fd2b50f
commit
1e97205c34
@ -1,7 +1,7 @@
|
||||
package golog
|
||||
|
||||
import (
|
||||
"go.dtapp.net/goip"
|
||||
"go.dtapp.net/library/utils/goip"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
@ -1,7 +1,7 @@
|
||||
package golog
|
||||
|
||||
import (
|
||||
"go.dtapp.net/goip"
|
||||
"go.dtapp.net/library/utils/goip"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
@ -1,11 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: test-golang
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
@ -1,8 +0,0 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
*.log
|
||||
gomod.sh
|
||||
/vendor/
|
@ -1,44 +0,0 @@
|
||||
<h1>
|
||||
<a href="https://www.dtapp.net/">Golang Ip</a>
|
||||
</h1>
|
||||
|
||||
📦 Golang Ip库组件
|
||||
|
||||
[comment]: <> (go)
|
||||
[![godoc](https://pkg.go.dev/badge/go.dtapp.net/goip?status.svg)](https://pkg.go.dev/go.dtapp.net/goip)
|
||||
[![goproxy.cn](https://goproxy.cn/stats/go.dtapp.net/goip/badges/download-count.svg)](https://goproxy.cn/stats/go.dtapp.net/goip)
|
||||
[![goreportcard.com](https://goreportcard.com/badge/go.dtapp.net/goip )](https://goreportcard.com/report/go.dtapp.net/goip)
|
||||
[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/go.dtapp.net/goip)
|
||||
|
||||
#### 安装使用
|
||||
|
||||
```go
|
||||
go get -v -u go.dtapp.net/goip
|
||||
```
|
||||
|
||||
#### 导入
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.dtapp.net/goip"
|
||||
)
|
||||
```
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"go.dtapp.net/goip"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGoIp(t *testing.T) {
|
||||
// 获取Mac地址
|
||||
t.Log(goip.GetMacAddr())
|
||||
// 内网ip
|
||||
t.Log(goip.GetInsideIp())
|
||||
// 外网ip
|
||||
t.Log(goip.GetOutsideIp())
|
||||
}
|
||||
|
||||
```
|
@ -1,89 +0,0 @@
|
||||
package goip
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
ipv4 = "IPV4"
|
||||
ipv6 = "IPV6"
|
||||
)
|
||||
|
||||
type AnalyseResult struct {
|
||||
IP string `json:"ip,omitempty"` // 输入的ip地址
|
||||
Country string `json:"country,omitempty"` // 国家或地区
|
||||
Province string `json:"province,omitempty"` // 省份
|
||||
City string `json:"city,omitempty"` // 城市
|
||||
Area string `json:"area,omitempty"` // 区域
|
||||
Isp string `json:"isp,omitempty"` // 运营商
|
||||
}
|
||||
|
||||
func (c *Client) Analyse(item string) AnalyseResult {
|
||||
isIp := c.isIpv4OrIpv6(item)
|
||||
switch isIp {
|
||||
case ipv4:
|
||||
info := c.V4db.Find(item)
|
||||
search, err := c.V4Region.MemorySearch(item)
|
||||
if err != nil {
|
||||
return AnalyseResult{
|
||||
IP: info.IP,
|
||||
Country: info.Country,
|
||||
Area: info.Area,
|
||||
}
|
||||
} else {
|
||||
return AnalyseResult{
|
||||
IP: search.IP,
|
||||
Country: search.Country,
|
||||
Province: search.Province,
|
||||
City: search.City,
|
||||
Isp: info.Area,
|
||||
}
|
||||
}
|
||||
case ipv6:
|
||||
info := c.V6db.Find(item)
|
||||
return AnalyseResult{
|
||||
IP: info.IP,
|
||||
Country: info.Country,
|
||||
Province: info.Province,
|
||||
City: info.City,
|
||||
Area: info.Area,
|
||||
Isp: info.Isp,
|
||||
}
|
||||
default:
|
||||
return AnalyseResult{}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckIpv4 检查数据是不是IPV4
|
||||
func (c *Client) CheckIpv4(ips string) bool {
|
||||
if len(ips) > 3 {
|
||||
return false
|
||||
}
|
||||
nums, err := strconv.Atoi(ips)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if nums < 0 || nums > 255 {
|
||||
return false
|
||||
}
|
||||
if len(ips) > 1 && ips[0] == '0' {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// CheckIpv6 检测是不是IPV6
|
||||
func (c *Client) CheckIpv6(ips string) bool {
|
||||
if ips == "" {
|
||||
return true
|
||||
}
|
||||
if len(ips) > 4 {
|
||||
return false
|
||||
}
|
||||
for _, val := range ips {
|
||||
if !((val >= '0' && val <= '9') || (val >= 'a' && val <= 'f') || (val >= 'A' && val <= 'F')) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package goip
|
||||
|
||||
import (
|
||||
"go.dtapp.net/goip/ip2region"
|
||||
v4 "go.dtapp.net/goip/v4"
|
||||
v6 "go.dtapp.net/goip/v6"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
V4Region ip2region.Ip2Region // IPV4
|
||||
V4db v4.Pointer // IPV4
|
||||
V6db v6.Pointer // IPV6
|
||||
}
|
||||
|
||||
// NewIp 实例化
|
||||
func NewIp() *Client {
|
||||
app := &Client{}
|
||||
v4Num := app.V4db.InitIPV4Data()
|
||||
log.Printf("IPV4 库加载完成 共加载:%d 条 IP 记录\n", v4Num)
|
||||
v6Num := app.V6db.InitIPV4Data()
|
||||
log.Printf("IPV6 库加载完成 共加载:%d 条 IP 记录\n", v6Num)
|
||||
return app
|
||||
}
|
||||
|
||||
func (c *Client) Ipv4(ip string) (res v4.Result, resInfo ip2region.IpInfo) {
|
||||
res = c.V4db.Find(ip)
|
||||
resInfo, _ = c.V4Region.MemorySearch(ip)
|
||||
return res, resInfo
|
||||
}
|
||||
|
||||
func (c *Client) Ipv6(ip string) (res v6.Result) {
|
||||
res = c.V6db.Find(ip)
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Client) isIpv4OrIpv6(ip string) string {
|
||||
if len(ip) < 7 {
|
||||
return ""
|
||||
}
|
||||
arrIpv4 := strings.Split(ip, ".")
|
||||
if len(arrIpv4) == 4 {
|
||||
//. 判断IPv4
|
||||
for _, val := range arrIpv4 {
|
||||
if !c.CheckIpv4(val) {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return ipv4
|
||||
}
|
||||
arrIpv6 := strings.Split(ip, ":")
|
||||
if len(arrIpv6) == 8 {
|
||||
// 判断Ipv6
|
||||
for _, val := range arrIpv6 {
|
||||
if !c.CheckIpv6(val) {
|
||||
return "Neither"
|
||||
}
|
||||
}
|
||||
return ipv6
|
||||
}
|
||||
return ""
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package ip2region
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func getOnline() ([]byte, error) {
|
||||
resp, err := http.Get("https://ghproxy.com/?q=https://github.com/lionsoul2014/ip2region/blob/master/data/ip2region.db?raw=true")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
return body, err
|
||||
}
|
Binary file not shown.
@ -1,58 +0,0 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/binary"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// 解密key
|
||||
// https://zhangzifan.com/update-qqwry-dat.html
|
||||
func getKey() (uint32, error) {
|
||||
resp, err := http.Get("https://update.cz88.net/ip/copywrite.rar")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if body, err := ioutil.ReadAll(resp.Body); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
// @see https://stackoverflow.com/questions/34078427/how-to-read-packed-binary-data-in-go
|
||||
return binary.LittleEndian.Uint32(body[5*4:]), nil
|
||||
}
|
||||
}
|
||||
|
||||
// 在线获取内容
|
||||
func getOnline() ([]byte, error) {
|
||||
resp, err := http.Get("https://update.cz88.net/ip/qqwry.rar")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if body, err := ioutil.ReadAll(resp.Body); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if key, err := getKey(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for i := 0; i < 0x200; i++ {
|
||||
key = key * 0x805
|
||||
key++
|
||||
key = key & 0xff
|
||||
|
||||
body[i] = byte(uint32(body[i]) ^ key)
|
||||
}
|
||||
|
||||
reader, err := zlib.NewReader(bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ioutil.ReadAll(reader)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"go.dtapp.net/gostring"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
var (
|
||||
header []byte
|
||||
country []byte
|
||||
area []byte
|
||||
offset uint32
|
||||
start uint32
|
||||
end uint32
|
||||
)
|
||||
|
||||
//go:embed qqwry.dat
|
||||
var dat []byte
|
||||
|
||||
type Pointer struct {
|
||||
Offset uint32
|
||||
ItemLen uint32
|
||||
IndexLen uint32
|
||||
}
|
||||
|
||||
// Result 返回
|
||||
type Result struct {
|
||||
IP string `json:"ip,omitempty"` // 输入的ip地址
|
||||
Country string `json:"country,omitempty"` // 国家或地区
|
||||
Area string `json:"area,omitempty"` // 区域
|
||||
}
|
||||
|
||||
// InitIPV4Data 加载
|
||||
func (q *Pointer) InitIPV4Data() int64 {
|
||||
buf := dat[0:8]
|
||||
start := binary.LittleEndian.Uint32(buf[:4])
|
||||
end := binary.LittleEndian.Uint32(buf[4:])
|
||||
|
||||
return int64((end-start)/7 + 1)
|
||||
}
|
||||
|
||||
// ReadData 从文件中读取数据
|
||||
func (q *Pointer) readData(length uint32) (rs []byte) {
|
||||
end := q.Offset + length
|
||||
dataNum := uint32(len(dat))
|
||||
if q.Offset > dataNum {
|
||||
return nil
|
||||
}
|
||||
|
||||
if end > dataNum {
|
||||
end = dataNum
|
||||
}
|
||||
rs = dat[q.Offset:end]
|
||||
q.Offset = end
|
||||
return rs
|
||||
}
|
||||
|
||||
// Find ip地址查询对应归属地信息
|
||||
func (q *Pointer) Find(ip string) (res Result) {
|
||||
|
||||
// 赋值
|
||||
res.IP = ip
|
||||
if net.ParseIP("61.241.55.180").To4() == nil {
|
||||
// 不是ip地址
|
||||
return res
|
||||
}
|
||||
|
||||
q.Offset = 0
|
||||
|
||||
// 偏移
|
||||
offset = q.searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4()))
|
||||
if offset <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
q.Offset = offset + q.ItemLen
|
||||
|
||||
country, area = q.getAddr()
|
||||
|
||||
enc := simplifiedchinese.GBK.NewDecoder()
|
||||
|
||||
res.Country, _ = enc.String(string(country))
|
||||
res.Country = gostring.SpaceAndLineBreak(res.Country)
|
||||
|
||||
res.Area, _ = enc.String(string(area))
|
||||
|
||||
// Delete CZ88.NET (防止不相关的信息产生干扰)
|
||||
if res.Area == " CZ88.NET" || res.Area == "" {
|
||||
res.Area = ""
|
||||
} else {
|
||||
res.Area = " " + res.Area
|
||||
}
|
||||
|
||||
res.Area = gostring.SpaceAndLineBreak(res.Area)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取地址信息
|
||||
func (q *Pointer) getAddr() ([]byte, []byte) {
|
||||
mode := q.readData(1)[0]
|
||||
if mode == 0x01 {
|
||||
// [IP][0x01][国家和地区信息的绝对偏移地址]
|
||||
q.Offset = byteToUInt32(q.readData(3))
|
||||
return q.getAddr()
|
||||
}
|
||||
// [IP][0x02][信息的绝对偏移][...] or [IP][国家][...]
|
||||
_offset := q.Offset - 1
|
||||
c1 := q.readArea(_offset)
|
||||
if mode == 0x02 {
|
||||
q.Offset = 4 + _offset
|
||||
} else {
|
||||
q.Offset = _offset + uint32(1+len(c1))
|
||||
}
|
||||
c2 := q.readArea(q.Offset)
|
||||
return c1, c2
|
||||
}
|
||||
|
||||
// 读取区
|
||||
func (q *Pointer) readArea(offset uint32) []byte {
|
||||
q.Offset = offset
|
||||
mode := q.readData(1)[0]
|
||||
if mode == 0x01 || mode == 0x02 {
|
||||
return q.readArea(byteToUInt32(q.readData(3)))
|
||||
}
|
||||
q.Offset = offset
|
||||
return q.readString()
|
||||
}
|
||||
|
||||
// 读取字符串
|
||||
func (q *Pointer) readString() []byte {
|
||||
data := make([]byte, 0)
|
||||
for {
|
||||
buf := q.readData(1)
|
||||
if buf[0] == 0 {
|
||||
break
|
||||
}
|
||||
data = append(data, buf[0])
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// 搜索索引
|
||||
func (q *Pointer) searchIndex(ip uint32) uint32 {
|
||||
q.ItemLen = 4
|
||||
q.IndexLen = 7
|
||||
header = dat[0:8]
|
||||
start = binary.LittleEndian.Uint32(header[:4])
|
||||
end = binary.LittleEndian.Uint32(header[4:])
|
||||
|
||||
buf := make([]byte, q.IndexLen)
|
||||
|
||||
for {
|
||||
mid := start + q.IndexLen*(((end-start)/q.IndexLen)>>1)
|
||||
buf = dat[mid : mid+q.IndexLen]
|
||||
_ip := binary.LittleEndian.Uint32(buf[:q.ItemLen])
|
||||
|
||||
if end-start == q.IndexLen {
|
||||
if ip >= binary.LittleEndian.Uint32(dat[end:end+q.ItemLen]) {
|
||||
buf = dat[end : end+q.IndexLen]
|
||||
}
|
||||
return byteToUInt32(buf[q.ItemLen:])
|
||||
}
|
||||
|
||||
if _ip > ip {
|
||||
end = mid
|
||||
} else if _ip < ip {
|
||||
start = mid
|
||||
} else if _ip == ip {
|
||||
return byteToUInt32(buf[q.ItemLen:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 字节转UInt32
|
||||
func byteToUInt32(data []byte) uint32 {
|
||||
i := uint32(data[0]) & 0xff
|
||||
i |= (uint32(data[1]) << 8) & 0xff00
|
||||
i |= (uint32(data[2]) << 16) & 0xff0000
|
||||
return i
|
||||
}
|
||||
|
||||
// OnlineDownload 在线下载
|
||||
func (q *Pointer) OnlineDownload() (err error) {
|
||||
tmpData, err := getOnline()
|
||||
if err != nil {
|
||||
return errors.New("下载失败")
|
||||
}
|
||||
if err := ioutil.WriteFile("./qqwry.dat", tmpData, 0644); err == nil {
|
||||
log.Printf("已下载最新 纯真 IPv4数据库 %s ", "./qqwry.dat")
|
||||
} else {
|
||||
return errors.New("保存失败")
|
||||
}
|
||||
return nil
|
||||
}
|
Binary file not shown.
@ -1,226 +0,0 @@
|
||||
package v6
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"go.dtapp.net/gostring"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
header []byte
|
||||
country []byte
|
||||
area []byte
|
||||
v6ip uint64
|
||||
offset uint32
|
||||
start uint32
|
||||
end uint32
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
IP string `json:"ip,omitempty"` // 输入的ip地址
|
||||
Country string `json:"country,omitempty"` // 国家
|
||||
Province string `json:"province,omitempty"` // 省份
|
||||
City string `json:"city,omitempty"` // 城市
|
||||
Area string `json:"area,omitempty"` // 区域
|
||||
Isp string `json:"isp,omitempty"` // 运营商
|
||||
}
|
||||
|
||||
//go:embed ipv6wry.db
|
||||
var dat []byte
|
||||
|
||||
type Pointer struct {
|
||||
Offset uint32
|
||||
ItemLen uint32
|
||||
IndexLen uint32
|
||||
}
|
||||
|
||||
// InitIPV4Data 加载
|
||||
func (q *Pointer) InitIPV4Data() int64 {
|
||||
buf := dat[0:8]
|
||||
start := binary.LittleEndian.Uint32(buf[:4])
|
||||
end := binary.LittleEndian.Uint32(buf[4:])
|
||||
|
||||
return int64((end-start)/7 + 1)
|
||||
}
|
||||
|
||||
// ReadData 从文件中读取数据
|
||||
func (q *Pointer) readData(length uint32) (rs []byte) {
|
||||
end := q.Offset + length
|
||||
dataNum := uint32(len(dat))
|
||||
if q.Offset > dataNum {
|
||||
return nil
|
||||
}
|
||||
|
||||
if end > dataNum {
|
||||
end = dataNum
|
||||
}
|
||||
rs = dat[q.Offset:end]
|
||||
q.Offset = end
|
||||
return rs
|
||||
}
|
||||
|
||||
// Find ip地址查询对应归属地信息
|
||||
func (q *Pointer) Find(ip string) (res Result) {
|
||||
|
||||
res = Result{}
|
||||
res.IP = ip
|
||||
q.Offset = 0
|
||||
|
||||
tp := big.NewInt(0)
|
||||
op := big.NewInt(0)
|
||||
tp.SetBytes(net.ParseIP(ip).To16())
|
||||
op.SetString("18446744073709551616", 10)
|
||||
op.Div(tp, op)
|
||||
tp.SetString("FFFFFFFFFFFFFFFF", 16)
|
||||
op.And(op, tp)
|
||||
|
||||
v6ip = op.Uint64()
|
||||
offset = q.searchIndex(v6ip)
|
||||
q.Offset = offset
|
||||
|
||||
country, area = q.getAddr()
|
||||
|
||||
// 解析地区数据
|
||||
info := strings.Split(string(country), "\t")
|
||||
if len(info) > 0 {
|
||||
i := 1
|
||||
for {
|
||||
if i > len(info) {
|
||||
break
|
||||
}
|
||||
switch i {
|
||||
case 1:
|
||||
res.Country = info[i-1]
|
||||
res.Country = gostring.SpaceAndLineBreak(res.Country)
|
||||
case 2:
|
||||
res.Province = info[i-1]
|
||||
res.Province = gostring.SpaceAndLineBreak(res.Province)
|
||||
case 3:
|
||||
res.City = info[i-1]
|
||||
res.City = gostring.SpaceAndLineBreak(res.City)
|
||||
case 4:
|
||||
res.Area = info[i-1]
|
||||
res.Area = gostring.SpaceAndLineBreak(res.Area)
|
||||
}
|
||||
i++ // 自增
|
||||
}
|
||||
} else {
|
||||
res.Country = string(country)
|
||||
res.Country = gostring.SpaceAndLineBreak(res.Country)
|
||||
}
|
||||
// 运营商
|
||||
res.Isp = string(area)
|
||||
|
||||
// Delete ZX (防止不相关的信息产生干扰)
|
||||
if res.Isp == "ZX" || res.Isp == "" {
|
||||
res.Isp = ""
|
||||
} else {
|
||||
res.Isp = " " + res.Isp
|
||||
}
|
||||
|
||||
res.Isp = gostring.SpaceAndLineBreak(res.Isp)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (q *Pointer) getAddr() ([]byte, []byte) {
|
||||
mode := q.readData(1)[0]
|
||||
if mode == 0x01 {
|
||||
// [IP][0x01][国家和地区信息的绝对偏移地址]
|
||||
q.Offset = byteToUInt32(q.readData(3))
|
||||
return q.getAddr()
|
||||
}
|
||||
// [IP][0x02][信息的绝对偏移][...] or [IP][国家][...]
|
||||
_offset := q.Offset - 1
|
||||
c1 := q.readArea(_offset)
|
||||
if mode == 0x02 {
|
||||
q.Offset = 4 + _offset
|
||||
} else {
|
||||
q.Offset = _offset + uint32(1+len(c1))
|
||||
}
|
||||
c2 := q.readArea(q.Offset)
|
||||
return c1, c2
|
||||
}
|
||||
|
||||
func (q *Pointer) readArea(offset uint32) []byte {
|
||||
q.Offset = offset
|
||||
mode := q.readData(1)[0]
|
||||
if mode == 0x01 || mode == 0x02 {
|
||||
return q.readArea(byteToUInt32(q.readData(3)))
|
||||
}
|
||||
q.Offset = offset
|
||||
return q.readString()
|
||||
}
|
||||
|
||||
func (q *Pointer) readString() []byte {
|
||||
data := make([]byte, 0)
|
||||
for {
|
||||
buf := q.readData(1)
|
||||
if buf[0] == 0 {
|
||||
break
|
||||
}
|
||||
data = append(data, buf[0])
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (q *Pointer) searchIndex(ip uint64) uint32 {
|
||||
|
||||
q.ItemLen = 8
|
||||
q.IndexLen = 11
|
||||
|
||||
header = dat[8:24]
|
||||
start = binary.LittleEndian.Uint32(header[8:])
|
||||
counts := binary.LittleEndian.Uint32(header[:8])
|
||||
end = start + counts*q.IndexLen
|
||||
|
||||
buf := make([]byte, q.IndexLen)
|
||||
|
||||
for {
|
||||
mid := start + q.IndexLen*(((end-start)/q.IndexLen)>>1)
|
||||
buf = dat[mid : mid+q.IndexLen]
|
||||
_ip := binary.LittleEndian.Uint64(buf[:q.ItemLen])
|
||||
|
||||
if end-start == q.IndexLen {
|
||||
if ip >= binary.LittleEndian.Uint64(dat[end:end+q.ItemLen]) {
|
||||
buf = dat[end : end+q.IndexLen]
|
||||
}
|
||||
return byteToUInt32(buf[q.ItemLen:])
|
||||
}
|
||||
|
||||
if _ip > ip {
|
||||
end = mid
|
||||
} else if _ip < ip {
|
||||
start = mid
|
||||
} else if _ip == ip {
|
||||
return byteToUInt32(buf[q.ItemLen:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func byteToUInt32(data []byte) uint32 {
|
||||
i := uint32(data[0]) & 0xff
|
||||
i |= (uint32(data[1]) << 8) & 0xff00
|
||||
i |= (uint32(data[2]) << 16) & 0xff0000
|
||||
return i
|
||||
}
|
||||
|
||||
// OnlineDownload 在线下载
|
||||
func (q *Pointer) OnlineDownload() (err error) {
|
||||
tmpData, err := getOnline()
|
||||
if err != nil {
|
||||
return errors.New("下载失败")
|
||||
}
|
||||
if err := ioutil.WriteFile("./ipv6wry.db", tmpData, 0644); err == nil {
|
||||
log.Printf("已下载最新 ZX IPv6数据库 %s ", "./ipv6wry.db")
|
||||
} else {
|
||||
return errors.New("保存失败")
|
||||
}
|
||||
return nil
|
||||
}
|
Binary file not shown.
@ -1,3 +0,0 @@
|
||||
package goip
|
||||
|
||||
const Version = "1.0.16"
|
@ -1,17 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: Test
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
||||
- name: Benchmark
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -bench=. -benchmem
|
@ -1,8 +0,0 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
*.log
|
||||
gomod.sh
|
||||
/vendor/
|
@ -1,47 +0,0 @@
|
||||
package gojson
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
func Encode(v interface{}) (string, error) {
|
||||
bytes, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(bytes), nil
|
||||
}
|
||||
|
||||
func MarshalToString(msg interface{}) (string, error) {
|
||||
j, e := json.Marshal(msg)
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
return string(j), nil
|
||||
}
|
||||
|
||||
func JsonDecode(data string) (map[string]interface{}, error) {
|
||||
var dat map[string]interface{}
|
||||
err := json.Unmarshal([]byte(data), &dat)
|
||||
return dat, err
|
||||
}
|
||||
|
||||
func JsonDecodeNoError(data string) map[string]interface{} {
|
||||
var dat map[string]interface{}
|
||||
_ = json.Unmarshal([]byte(data), &dat)
|
||||
return dat
|
||||
}
|
||||
|
||||
func JsonEncode(data interface{}) (string, error) {
|
||||
jsons, err := json.Marshal(data)
|
||||
return string(jsons), err
|
||||
}
|
||||
|
||||
func JsonEncodeNoError(data interface{}) string {
|
||||
jsons, _ := json.Marshal(data)
|
||||
return string(jsons)
|
||||
}
|
||||
|
||||
func JsonDecodesNoError(data string) []string {
|
||||
var dat []string
|
||||
_ = json.Unmarshal([]byte(data), &dat)
|
||||
return dat
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
package gojson
|
||||
|
||||
const Version = "1.0.0"
|
@ -1,11 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: test-golang
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
@ -1,9 +0,0 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
*.log
|
||||
gomod.sh
|
||||
/vendor/
|
||||
time_test.go
|
@ -1,25 +0,0 @@
|
||||
<h1>
|
||||
<a href="https://www.dtapp.net/">Golang Log</a>
|
||||
</h1>
|
||||
|
||||
📦 Golang 日志组件
|
||||
|
||||
[comment]: <> (go)
|
||||
[![godoc](https://pkg.go.dev/badge/go.dtapp.net/golog?status.svg)](https://pkg.go.dev/go.dtapp.net/golog)
|
||||
[![goproxy.cn](https://goproxy.cn/stats/go.dtapp.net/golog/badges/download-count.svg)](https://goproxy.cn/stats/go.dtapp.net/golog)
|
||||
[![goreportcard.com](https://goreportcard.com/badge/go.dtapp.net/golog )](https://goreportcard.com/report/go.dtapp.net/golog)
|
||||
[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/go.dtapp.net/golog)
|
||||
|
||||
#### 安装使用
|
||||
|
||||
```go
|
||||
go get -v -u go.dtapp.net/golog
|
||||
```
|
||||
|
||||
#### 导入
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.dtapp.net/golog"
|
||||
)
|
||||
```
|
@ -1,3 +0,0 @@
|
||||
package golog
|
||||
|
||||
const Version = "1.0.13"
|
@ -1,11 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: test-golang
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
@ -1,8 +0,0 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
*.log
|
||||
gomod.sh
|
||||
/vendor/
|
@ -1,25 +0,0 @@
|
||||
<h1>
|
||||
<a href="https://www.dtapp.net/">Golang MongoDB CRUD</a>
|
||||
</h1>
|
||||
|
||||
📦 Golang MongoDB CRUD 组件
|
||||
|
||||
[comment]: <> (go)
|
||||
[![godoc](https://pkg.go.dev/badge/go.dtapp.net/gomongo?status.svg)](https://pkg.go.dev/go.dtapp.net/gomongo)
|
||||
[![goproxy.cn](https://goproxy.cn/stats/go.dtapp.net/gomongo/badges/download-count.svg)](https://goproxy.cn/stats/go.dtapp.net/gomongo)
|
||||
[![goreportcard.com](https://goreportcard.com/badge/go.dtapp.net/gomongo)](https://goreportcard.com/report/go.dtapp.net/gomongo)
|
||||
[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/go.dtapp.net/gomongo)
|
||||
|
||||
#### 安装使用
|
||||
|
||||
```go
|
||||
go get -v -u go.dtapp.net/gomongo
|
||||
```
|
||||
|
||||
#### 导入
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.dtapp.net/gomongo"
|
||||
)
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue