update
This commit is contained in:
parent
83cfd8c5e7
commit
129514a159
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
.idea
|
||||
bin
|
||||
2
go.mod
2
go.mod
@ -2,4 +2,4 @@ module b612.me/sdk/whois
|
||||
|
||||
go 1.21.2
|
||||
|
||||
require golang.org/x/net v0.24.0
|
||||
require golang.org/x/net v0.28.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -1,2 +1,2 @@
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
|
||||
499
parse.go
499
parse.go
@ -16,13 +16,29 @@ func parse(domain string, result string) (Result, error) {
|
||||
data, err = dotJPParser(domain, result)
|
||||
case "tw":
|
||||
data, err = dotTWParser(domain, result)
|
||||
case "name":
|
||||
data, err = dotNameParser(domain, result)
|
||||
default:
|
||||
data, err = commonParser(domain, result)
|
||||
case "edu":
|
||||
data, err = dotEduParser(domain, result)
|
||||
case "int":
|
||||
data, err = dotIntParser(domain, result)
|
||||
case "ae":
|
||||
data, err = dotAeParser(domain, result)
|
||||
case "ai":
|
||||
data, err = commonParserWithDate(domain, result, false, false, false)
|
||||
case "am":
|
||||
data, err = dotAmParser(domain, result)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func commonParser(domain, data string) (Result, error) {
|
||||
return commonParserWithDate(domain, data, true, true, true)
|
||||
}
|
||||
|
||||
func commonParserWithDate(domain, data string, hasCreate bool, hasExpire bool, hasUpdate bool) (Result, error) {
|
||||
var res = Result{
|
||||
domain: domain,
|
||||
rawData: data,
|
||||
@ -34,8 +50,8 @@ func commonParser(domain, data string) (Result, error) {
|
||||
for _, line := range split {
|
||||
line = strings.TrimSpace(line)
|
||||
if !res.exists {
|
||||
for _, token := range []string{"Domain not found.", "No match for", "No match", "No Data Found", "No entries found", "No match for domain", "No matching record", "No Found", "No Object"} {
|
||||
if strings.HasPrefix(token, line) {
|
||||
for _, token := range []string{"No Object Found", "Domain not found.", "No match for", "No match", "No Data Found", "No entries found", "No match for domain", "No matching record", "No Found", "No Object"} {
|
||||
if strings.HasPrefix(line, token) {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
@ -43,6 +59,9 @@ func commonParser(domain, data string) (Result, error) {
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain Name:") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = hasUpdate
|
||||
res.hasRegisterDate = hasCreate
|
||||
res.hasExpireDate = hasExpire
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "Domain Name:"))
|
||||
}
|
||||
@ -50,13 +69,28 @@ func commonParser(domain, data string) (Result, error) {
|
||||
res.domainID = strings.TrimSpace(strings.TrimPrefix(line, "Registry Domain ID:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Updated Date:") {
|
||||
res.updateDate = parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Updated Date:")))
|
||||
tmpDate := parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Updated Date:")))
|
||||
if !tmpDate.IsZero() {
|
||||
res.updateDate = tmpDate
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "Creation Date:") {
|
||||
res.registerDate = parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Creation Date:")))
|
||||
tmpDate := parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Creation Date:")))
|
||||
if !tmpDate.IsZero() {
|
||||
res.registerDate = tmpDate
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "Registry Expiry Date:") {
|
||||
res.expireDate = parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Registry Expiry Date:")))
|
||||
tmpDate := parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Registry Expiry Date:")))
|
||||
if !tmpDate.IsZero() {
|
||||
res.expireDate = tmpDate
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrar Registration Expiration Date:") {
|
||||
tmpDate := parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Registrar Registration Expiration Date:")))
|
||||
if !tmpDate.IsZero() {
|
||||
res.expireDate = tmpDate
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrar:") {
|
||||
res.registar = strings.TrimSpace(strings.TrimPrefix(line, "Registrar:"))
|
||||
@ -65,6 +99,10 @@ func commonParser(domain, data string) (Result, error) {
|
||||
statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Status:")), " ")[0]] = struct{}{}
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain Status:") {
|
||||
if strings.Contains(line, "No Object Found") {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Domain Status:")), " ")[0]] = struct{}{}
|
||||
}
|
||||
if strings.HasPrefix(line, "Name Server:") {
|
||||
@ -73,9 +111,6 @@ func commonParser(domain, data string) (Result, error) {
|
||||
if strings.HasPrefix(line, "DNSSEC:") {
|
||||
res.dnssec = strings.TrimSpace(strings.TrimPrefix(line, "DNSSEC:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrar Registration Expiration Date:") {
|
||||
res.expireDate = parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Registrar Registration Expiration Date:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrant Name:") {
|
||||
r.Name = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Name:"))
|
||||
}
|
||||
@ -194,6 +229,61 @@ func commonParser(domain, data string) (Result, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func dotNameParser(domain, data string) (Result, error) {
|
||||
var res = Result{
|
||||
domain: domain,
|
||||
rawData: data,
|
||||
}
|
||||
var r, a, t PersonalInfo
|
||||
|
||||
split := strings.Split(data, "\n")
|
||||
statusMap := make(map[string]struct{})
|
||||
for _, line := range split {
|
||||
line = strings.TrimSpace(line)
|
||||
if !res.exists {
|
||||
for _, token := range []string{"No match for"} {
|
||||
if strings.HasPrefix(line, token) {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain Name:") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = false
|
||||
res.hasRegisterDate = false
|
||||
res.hasExpireDate = false
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "Domain Name:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registry Domain ID:") {
|
||||
res.domainID = strings.TrimSpace(strings.TrimPrefix(line, "Registry Domain ID:"))
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "Registrar:") {
|
||||
res.registar = strings.TrimSpace(strings.TrimPrefix(line, "Registrar:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Status:") {
|
||||
statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Status:")), " ")[0]] = struct{}{}
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain Status:") {
|
||||
if strings.Contains(line, "No Object Found") {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Domain Status:")), " ")[0]] = struct{}{}
|
||||
}
|
||||
}
|
||||
for status := range statusMap {
|
||||
res.statusRaw = append(res.statusRaw, status)
|
||||
}
|
||||
res.registerInfo = r
|
||||
res.adminInfo = a
|
||||
res.techInfo = t
|
||||
return res, nil
|
||||
|
||||
}
|
||||
|
||||
func dotCNParser(domain, data string) (Result, error) {
|
||||
var res = Result{
|
||||
domain: domain,
|
||||
@ -204,6 +294,13 @@ func dotCNParser(domain, data string) (Result, error) {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
if strings.HasPrefix(strings.TrimSpace(data), "the Domain Name you apply can not be registered online") {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
res.hasUpdateDate = false
|
||||
res.hasRegisterDate = true
|
||||
res.hasExpireDate = true
|
||||
res.exists = true
|
||||
statusMap := make(map[string]struct{})
|
||||
split := strings.Split(data, "\n")
|
||||
@ -267,6 +364,9 @@ func dotJPParser(domain, data string) (Result, error) {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "[Domain Name]") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = true
|
||||
res.hasRegisterDate = true
|
||||
res.hasExpireDate = true
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "[Domain Name]"))
|
||||
}
|
||||
@ -341,6 +441,9 @@ func dotTWParser(domain, data string) (Result, error) {
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain Name:") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = true
|
||||
res.hasRegisterDate = true
|
||||
res.hasExpireDate = true
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "Domain Name:"))
|
||||
}
|
||||
@ -398,8 +501,373 @@ func dotTWParser(domain, data string) (Result, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func dotEduParser(domain, data string) (Result, error) {
|
||||
var res = Result{
|
||||
domain: domain,
|
||||
rawData: data,
|
||||
}
|
||||
split := strings.Split(data, "\n")
|
||||
startNs := false
|
||||
var currentStatus uint8 = 0
|
||||
var startIdx int
|
||||
var r, a, t, p PersonalInfo
|
||||
for idx, line := range split {
|
||||
line = strings.TrimSpace(line)
|
||||
if startNs && len(line) == 0 {
|
||||
startNs = false
|
||||
}
|
||||
if strings.HasPrefix(line, "NO MATCH:") {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain Name:") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = true
|
||||
res.hasRegisterDate = true
|
||||
res.hasExpireDate = true
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "Domain Name:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain record activated:") {
|
||||
res.registerDate = parseEduDate(strings.TrimSpace(strings.TrimPrefix(line, "Domain record activated:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain record last updated:") {
|
||||
res.updateDate = parseEduDate(strings.TrimSpace(strings.TrimPrefix(line, "Domain record last updated:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain expires:") {
|
||||
res.expireDate = parseEduDate(strings.TrimSpace(strings.TrimPrefix(line, "Domain expires:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrant:") {
|
||||
currentStatus = 1
|
||||
startIdx = idx
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "Administrative Contact:") {
|
||||
currentStatus = 2
|
||||
startIdx = idx
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "Technical Contact:") {
|
||||
currentStatus = 3
|
||||
startIdx = idx
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "Name Servers:") {
|
||||
startNs = true
|
||||
continue
|
||||
}
|
||||
if startNs {
|
||||
res.nsServers = append(res.nsServers, line)
|
||||
}
|
||||
if currentStatus > 0 {
|
||||
switch idx - startIdx {
|
||||
case 1:
|
||||
p.Name = line
|
||||
case 2, 3, 4, 5:
|
||||
p.Addr += line
|
||||
case 6:
|
||||
p.Phone = line
|
||||
case 7:
|
||||
p.Email = line
|
||||
}
|
||||
if len(line) == 0 {
|
||||
switch currentStatus {
|
||||
case 1:
|
||||
r = p
|
||||
case 2:
|
||||
a = p
|
||||
case 3:
|
||||
t = p
|
||||
}
|
||||
currentStatus = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
res.registerInfo = r
|
||||
res.adminInfo = a
|
||||
res.techInfo = t
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func dotIntParser(domain, data string) (Result, error) {
|
||||
var res = Result{
|
||||
domain: domain,
|
||||
rawData: data,
|
||||
}
|
||||
split := strings.Split(data, "\n")
|
||||
var currentStatus uint8 = 0
|
||||
var r, a, t, p PersonalInfo
|
||||
for _, line := range split {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.Contains(line, "but this server does not have") {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
if strings.HasPrefix(line, "domain:") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = true
|
||||
res.hasRegisterDate = true
|
||||
res.hasExpireDate = false
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "domain:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "created:") {
|
||||
res.registerDate = parseYMDDate(strings.TrimSpace(strings.TrimPrefix(line, "created:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "changed:") {
|
||||
res.updateDate = parseYMDDate(strings.TrimSpace(strings.TrimPrefix(line, "changed:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "organisation:") {
|
||||
currentStatus = 1
|
||||
p = PersonalInfo{
|
||||
Org: strings.TrimSpace(strings.TrimPrefix(line, "organisation:")),
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "contact:") && strings.Contains(line, "administrative") {
|
||||
currentStatus = 2
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "contact:") && strings.Contains(line, "technical") {
|
||||
currentStatus = 3
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "nserver:") {
|
||||
nsList := strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "nserver:")), " ")
|
||||
for idx, ns := range nsList {
|
||||
if idx == 0 {
|
||||
res.nsServers = append(res.nsServers, ns)
|
||||
continue
|
||||
}
|
||||
res.nsIps = append(res.nsIps, ns)
|
||||
}
|
||||
}
|
||||
if currentStatus > 0 {
|
||||
if strings.HasPrefix(line, "address:") {
|
||||
p.Addr += strings.TrimSpace(strings.TrimPrefix(line, "address:")) + "\n"
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "phone:") {
|
||||
p.Phone = strings.TrimSpace(strings.TrimPrefix(line, "phone:"))
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "e-mail:") {
|
||||
p.Email = strings.TrimSpace(strings.TrimPrefix(line, "e-mail:"))
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "fax-no:") {
|
||||
p.Fax = strings.TrimSpace(strings.TrimPrefix(line, "fax-no:"))
|
||||
continue
|
||||
}
|
||||
if len(line) == 0 {
|
||||
p.Addr = strings.TrimSpace(p.Addr)
|
||||
switch currentStatus {
|
||||
case 1:
|
||||
r = p
|
||||
case 2:
|
||||
a = p
|
||||
case 3:
|
||||
t = p
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res.registerInfo = r
|
||||
res.adminInfo = a
|
||||
res.techInfo = t
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func dotAeParser(domain, data string) (Result, error) {
|
||||
var res = Result{
|
||||
domain: domain,
|
||||
rawData: data,
|
||||
}
|
||||
var r, a, t PersonalInfo
|
||||
|
||||
split := strings.Split(data, "\n")
|
||||
statusMap := make(map[string]struct{})
|
||||
for _, line := range split {
|
||||
line = strings.TrimSpace(line)
|
||||
if !res.exists {
|
||||
for _, token := range []string{"No Data Found"} {
|
||||
if strings.HasPrefix(line, token) {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain Name:") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = false
|
||||
res.hasRegisterDate = false
|
||||
res.hasExpireDate = false
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "Domain Name:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrar Name:") {
|
||||
res.registar = strings.TrimSpace(strings.TrimPrefix(line, "Registrar Name:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Status:") {
|
||||
statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Status:")), " ")[0]] = struct{}{}
|
||||
}
|
||||
if strings.HasPrefix(line, "Name Server:") {
|
||||
res.nsServers = append(res.nsServers, strings.TrimSpace(strings.TrimPrefix(line, "Name Server:")))
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "Registrant Contact Name:") {
|
||||
r.Name = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Contact Name:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrant Contact Organisation::") {
|
||||
r.Org = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Contact Organisation:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrant Contact Email:") {
|
||||
r.Email = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Contact Email:"))
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "Tech Contact Name:") {
|
||||
t.Name = strings.TrimSpace(strings.TrimPrefix(line, "Tech Contact Name:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Tech Contact Organisation::") {
|
||||
t.Org = strings.TrimSpace(strings.TrimPrefix(line, "Tech Contact Organisation:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Tech Contact Email:") {
|
||||
t.Email = strings.TrimSpace(strings.TrimPrefix(line, "Tech Contact Email:"))
|
||||
}
|
||||
}
|
||||
for status := range statusMap {
|
||||
res.statusRaw = append(res.statusRaw, status)
|
||||
}
|
||||
res.registerInfo = r
|
||||
res.adminInfo = a
|
||||
res.techInfo = t
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func dotAmParser(domain, data string) (Result, error) {
|
||||
var res = Result{
|
||||
domain: domain,
|
||||
rawData: data,
|
||||
}
|
||||
split := strings.Split(data, "\n")
|
||||
var currentStatus uint8 = 0
|
||||
statusMap := make(map[string]struct{})
|
||||
var r, a, t, p PersonalInfo
|
||||
startNs := false
|
||||
var tmpSlice []string
|
||||
for _, line := range split {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "Status:") {
|
||||
statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Status:")), " ")[0]] = struct{}{}
|
||||
}
|
||||
if strings.Contains(line, "No match") {
|
||||
res.exists = false
|
||||
return res, nil
|
||||
}
|
||||
if strings.HasPrefix(line, "Domain name:") {
|
||||
res.exists = true
|
||||
res.hasUpdateDate = true
|
||||
res.hasRegisterDate = true
|
||||
res.hasExpireDate = false
|
||||
res.nsServers = []string{}
|
||||
res.domain = strings.TrimSpace(strings.TrimPrefix(line, "Domain name:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registered:") {
|
||||
res.registerDate = parseYMDDate(strings.TrimSpace(strings.TrimPrefix(line, "Registered:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "Last modified:") {
|
||||
res.updateDate = parseYMDDate(strings.TrimSpace(strings.TrimPrefix(line, "Last modified:")))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrar:") {
|
||||
res.registar = strings.TrimSpace(strings.TrimPrefix(line, "Registrar:"))
|
||||
}
|
||||
if strings.HasPrefix(line, "Registrant:") {
|
||||
currentStatus = 1
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "Administrative contact:") {
|
||||
currentStatus = 2
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "Technical contact:") {
|
||||
currentStatus = 3
|
||||
p = PersonalInfo{}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "DNS servers (") {
|
||||
startNs = true
|
||||
continue
|
||||
}
|
||||
if startNs {
|
||||
tmp := strings.Split(line, "-")
|
||||
for idx, ns := range tmp {
|
||||
ns = strings.TrimSpace(ns)
|
||||
if idx == 0 {
|
||||
res.nsServers = append(res.nsServers, ns)
|
||||
continue
|
||||
}
|
||||
res.nsIps = append(res.nsIps, ns)
|
||||
}
|
||||
}
|
||||
if len(line) == 0 {
|
||||
startNs = false
|
||||
}
|
||||
if currentStatus > 0 {
|
||||
tmpSlice = append(tmpSlice, line)
|
||||
if len(line) == 0 {
|
||||
switch currentStatus {
|
||||
case 1:
|
||||
p.Addr = strings.Join(tmpSlice, "\n")
|
||||
tmpSlice = []string{}
|
||||
r = p
|
||||
case 2:
|
||||
if len(tmpSlice) > 2 {
|
||||
p.Addr = strings.Join(tmpSlice[:len(tmpSlice)-2], "\n")
|
||||
p.Phone = tmpSlice[len(tmpSlice)-1]
|
||||
p.Email = tmpSlice[len(tmpSlice)-2]
|
||||
} else {
|
||||
p.Addr = strings.Join(tmpSlice, "\n")
|
||||
}
|
||||
tmpSlice = []string{}
|
||||
a = p
|
||||
case 3:
|
||||
if len(tmpSlice) > 2 {
|
||||
p.Addr = strings.Join(tmpSlice[:len(tmpSlice)-2], "\n")
|
||||
p.Phone = tmpSlice[len(tmpSlice)-1]
|
||||
p.Email = tmpSlice[len(tmpSlice)-2]
|
||||
} else {
|
||||
p.Addr = strings.Join(tmpSlice, "\n")
|
||||
}
|
||||
tmpSlice = []string{}
|
||||
t = p
|
||||
}
|
||||
currentStatus = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
for status := range statusMap {
|
||||
res.statusRaw = append(res.statusRaw, status)
|
||||
}
|
||||
res.registerInfo = r
|
||||
res.adminInfo = a
|
||||
res.techInfo = t
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func parseDate(date string) time.Time {
|
||||
t, _ := time.Parse("2006-01-02T15:04:05Z", date)
|
||||
t, err := time.Parse("2006-01-02T15:04:05Z", date)
|
||||
if err == nil {
|
||||
t = t.In(time.Local)
|
||||
return t
|
||||
}
|
||||
t, err = time.Parse("2006-01-02T15:04:05-0700", date)
|
||||
t = t.In(time.Local)
|
||||
return t
|
||||
}
|
||||
@ -420,3 +888,16 @@ func parseJPDate(date string, onlyMD bool) time.Time {
|
||||
t = t.In(time.Local)
|
||||
return t
|
||||
}
|
||||
|
||||
func parseEduDate(date string) time.Time {
|
||||
//example 20-Dec-1996
|
||||
t, _ := time.Parse("02-Jan-2006", date)
|
||||
t = t.In(time.Local)
|
||||
return t
|
||||
}
|
||||
|
||||
func parseYMDDate(date string) time.Time {
|
||||
t, _ := time.Parse("2006-01-02", date)
|
||||
t = t.In(time.Local)
|
||||
return t
|
||||
}
|
||||
|
||||
122
parse_test.go
122
parse_test.go
@ -2,10 +2,128 @@ package whois
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWhois(t *testing.T) {
|
||||
func TestWhoisInfo(t *testing.T) {
|
||||
c := NewClient()
|
||||
fmt.Println(c.Whois("b612.in"))
|
||||
domain := "who.int"
|
||||
h, err := c.Whois(domain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
os.WriteFile("./bin/"+domain+".txt", []byte(h.RawData()), 0644)
|
||||
fmt.Println("Domain:", h.Domain())
|
||||
fmt.Println("Exists:", h.Exists())
|
||||
fmt.Println("RegistrarDate:", h.RegisterDate())
|
||||
fmt.Println("ExpireDate:", h.ExpireDate())
|
||||
fmt.Println("UpdateDate:", h.UpdateDate())
|
||||
fmt.Println("Status:", h.Status())
|
||||
fmt.Println("NsServers:", h.NsServers())
|
||||
fmt.Println("NsIp:", h.NsIps())
|
||||
fmt.Println("Dnssec:", h.Dnssec())
|
||||
fmt.Println("WhoisSer:", h.WhoisSer())
|
||||
fmt.Println("IanaID:", h.IanaID())
|
||||
fmt.Println("======RegisterInfo=======")
|
||||
fmt.Println("Name:", h.RegisterInfo().Name)
|
||||
fmt.Println("Organization:", h.RegisterInfo().Org)
|
||||
fmt.Println("Addr:", h.RegisterInfo().Addr)
|
||||
fmt.Println("State:", h.RegisterInfo().State)
|
||||
fmt.Println("Country:", h.RegisterInfo().Country)
|
||||
fmt.Println("Email:", h.RegisterInfo().Email)
|
||||
fmt.Println("Phone:", h.RegisterInfo().Phone)
|
||||
fmt.Println("Fax:", h.RegisterInfo().Fax)
|
||||
fmt.Println("======AdminInfo=======")
|
||||
fmt.Println("Name:", h.AdminInfo().Name)
|
||||
fmt.Println("Organization:", h.AdminInfo().Org)
|
||||
fmt.Println("Addr:", h.AdminInfo().Addr)
|
||||
fmt.Println("State:", h.AdminInfo().State)
|
||||
fmt.Println("Country:", h.AdminInfo().Country)
|
||||
fmt.Println("Email:", h.AdminInfo().Email)
|
||||
fmt.Println("Phone:", h.AdminInfo().Phone)
|
||||
fmt.Println("Fax:", h.AdminInfo().Fax)
|
||||
fmt.Println("======TechInfo=======")
|
||||
fmt.Println("Name:", h.TechInfo().Name)
|
||||
fmt.Println("Organization:", h.TechInfo().Org)
|
||||
fmt.Println("Addr:", h.TechInfo().Addr)
|
||||
fmt.Println("State:", h.TechInfo().State)
|
||||
fmt.Println("Country:", h.TechInfo().Country)
|
||||
fmt.Println("Email:", h.TechInfo().Email)
|
||||
fmt.Println("Phone:", h.TechInfo().Phone)
|
||||
fmt.Println("Fax:", h.TechInfo().Fax)
|
||||
fmt.Println("====================")
|
||||
fmt.Println("\nRaw:", h.RawData())
|
||||
|
||||
}
|
||||
|
||||
func TestWhois(t *testing.T) {
|
||||
os.MkdirAll("./bin", 0755)
|
||||
domainSuffix := []string{"com", "net", "org", "cn", "io", "me", "cc", "top", "xyz", "vip", "club", "site", "win", "bid",
|
||||
"loan", "ek", "kim", "ren", "ltd", "link", "red", "pro", "info", "mobi", "name", "tv", "ws", "asia",
|
||||
"biz", "gov", "edu", "mil", "int", "aero", "coop", "museum", "jobs", "travel", "xxx",
|
||||
"ac", "ad", "ae", "af", "ag", "ai", "al", "am", "an", "ao", "aq", "ar", "as", "at", "au", "aw", "az",
|
||||
"ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by", "bz",
|
||||
"ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co", "cr", "cu", "cv", "cx", "cy", "cz",
|
||||
"de", "dj", "dk", "dm", "do", "dz",
|
||||
"ec", "ee", "eg", "eh", "er", "es", "et", "eu",
|
||||
"fi", "fj", "fk", "fm", "fo", "fr",
|
||||
"ga", "gb", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp", "gq", "gr", "gs", "gt", "gu", "gw", "gy",
|
||||
"hk", "hm", "hn", "hr", "ht", "hu",
|
||||
"id", "ie", "il", "im", "in", "io", "iq", "ir", "is", "it",
|
||||
"je", "jm", "jo", "jp",
|
||||
"ke", "kg", "kh", "ki", "km", "kn", "kp", "kr", "kw", "ky", "kz",
|
||||
"la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly",
|
||||
"ma", "mc", "md", "mg", "mh", "mk", "ml", "mm", "mn", "mo", "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz",
|
||||
"na", "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz",
|
||||
"om",
|
||||
"pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "ps", "pt", "pw", "py",
|
||||
"qa",
|
||||
"re", "ro", "ru", "rw",
|
||||
"sa", "sb", "sc", "sd", "se", "sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "so", "sr", "st", "sv", "sy", "sz",
|
||||
"tc", "td", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", "to", "tp", "tr", "tt", "tv", "tw", "tz",
|
||||
"ua", "ug", "uk", "us", "uy", "uz",
|
||||
"va", "vc", "ve", "vg", "vi", "vn", "vu",
|
||||
"wf", "ws",
|
||||
"ye", "yt", "yu",
|
||||
"za", "zm", "zw"}
|
||||
prefix := "nic."
|
||||
c := NewClient()
|
||||
for idx, suffix := range domainSuffix {
|
||||
if idx < 50 {
|
||||
continue
|
||||
}
|
||||
domain := prefix + suffix
|
||||
if suffix == "cn" {
|
||||
domain = "cnnic.cn"
|
||||
}
|
||||
if suffix == "int" {
|
||||
domain = "who.int"
|
||||
}
|
||||
h, err := c.Whois(domain)
|
||||
if err != nil {
|
||||
fmt.Println(idx, domain, "net fail", err)
|
||||
continue
|
||||
}
|
||||
os.WriteFile("./bin/"+domain+".txt", []byte(h.RawData()), 0644)
|
||||
if !h.exists {
|
||||
fmt.Println(idx, h.Domain(), "fail")
|
||||
t.Fatal(domain, "not exists")
|
||||
}
|
||||
fmt.Println(idx, h.Domain(), "ok")
|
||||
fmt.Println(h.ExpireDate(), h.RegisterDate())
|
||||
if h.HasExpireDate() && h.ExpireDate().IsZero() {
|
||||
t.Fatal("ExpireDate is zero")
|
||||
}
|
||||
if h.Domain() == "" {
|
||||
t.Fatal("Domain is empty")
|
||||
}
|
||||
if h.HasRegisterDate() && h.RegisterDate().IsZero() {
|
||||
t.Fatal("RegisterDate is zero")
|
||||
}
|
||||
if len(h.NsServers()) == 0 {
|
||||
fmt.Println("NsServers is empty")
|
||||
}
|
||||
fmt.Println(h.Status())
|
||||
}
|
||||
}
|
||||
|
||||
89
whois.go
89
whois.go
@ -7,6 +7,7 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/proxy"
|
||||
@ -76,8 +77,12 @@ var statusMap = map[string]string{
|
||||
// DefaultClient is default whois client
|
||||
var DefaultClient = NewClient()
|
||||
|
||||
var defaultWhoisMap = map[string]string{}
|
||||
|
||||
// Client is whois client
|
||||
type Client struct {
|
||||
extCache map[string]string
|
||||
mu sync.Mutex
|
||||
dialer proxy.Dialer
|
||||
timeout time.Duration
|
||||
elapsed time.Duration
|
||||
@ -101,22 +106,42 @@ type PersonalInfo struct {
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
exists bool
|
||||
domain string
|
||||
domainID string
|
||||
rawData string
|
||||
registar string
|
||||
registerDate time.Time
|
||||
updateDate time.Time
|
||||
expireDate time.Time
|
||||
statusRaw []string
|
||||
nsServers []string
|
||||
dnssec string
|
||||
whoisSer string
|
||||
ianaID string
|
||||
registerInfo PersonalInfo
|
||||
adminInfo PersonalInfo
|
||||
techInfo PersonalInfo
|
||||
exists bool
|
||||
domain string
|
||||
domainID string
|
||||
rawData string
|
||||
registar string
|
||||
hasRegisterDate bool
|
||||
registerDate time.Time
|
||||
hasUpdateDate bool
|
||||
updateDate time.Time
|
||||
hasExpireDate bool
|
||||
expireDate time.Time
|
||||
statusRaw []string
|
||||
nsServers []string
|
||||
nsIps []string
|
||||
dnssec string
|
||||
whoisSer string
|
||||
ianaID string
|
||||
registerInfo PersonalInfo
|
||||
adminInfo PersonalInfo
|
||||
techInfo PersonalInfo
|
||||
}
|
||||
|
||||
func (r Result) NsIps() []string {
|
||||
return r.nsIps
|
||||
}
|
||||
|
||||
func (r Result) HasRegisterDate() bool {
|
||||
return r.hasRegisterDate
|
||||
}
|
||||
|
||||
func (r Result) HasUpdateDate() bool {
|
||||
return r.hasUpdateDate
|
||||
}
|
||||
|
||||
func (r Result) HasExpireDate() bool {
|
||||
return r.hasExpireDate
|
||||
}
|
||||
|
||||
func (r Result) Exists() bool {
|
||||
@ -189,12 +214,18 @@ func NewClient() *Client {
|
||||
dialer: &net.Dialer{
|
||||
Timeout: defTimeout,
|
||||
},
|
||||
timeout: defTimeout,
|
||||
extCache: make(map[string]string),
|
||||
timeout: defTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Whois(domain string, servers ...string) (Result, error) {
|
||||
data, err := c.whois(domain)
|
||||
if len(servers) == 0 {
|
||||
if v, ok := defaultWhoisMap[getExtension(domain)]; ok {
|
||||
servers = append(servers, v)
|
||||
}
|
||||
}
|
||||
data, err := c.whois(domain, servers...)
|
||||
if err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
@ -234,13 +265,21 @@ func (c *Client) whois(domain string, servers ...string) (result string, err err
|
||||
port = defWhoisPort
|
||||
} else {
|
||||
ext := getExtension(domain)
|
||||
result, err := c.rawQuery(ext, defWhoisServer, defWhoisPort)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("whois: query for whois server failed: %w", err)
|
||||
}
|
||||
server, port = getServer(result)
|
||||
if server == "" {
|
||||
return "", fmt.Errorf("%w: %s", errors.New("whois server not found"), domain)
|
||||
if _, ok := c.extCache[ext]; !ok {
|
||||
result, err := c.rawQuery(ext, defWhoisServer, defWhoisPort)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("whois: query for whois server failed: %w", err)
|
||||
}
|
||||
server, port = getServer(result)
|
||||
if server == "" {
|
||||
return "", fmt.Errorf("%w: %s", errors.New("whois server not found"), domain)
|
||||
}
|
||||
c.mu.Lock()
|
||||
c.extCache[ext] = fmt.Sprintf("%s:%s", server, port)
|
||||
c.mu.Unlock()
|
||||
} else {
|
||||
v := strings.Split(c.extCache[ext], ":")
|
||||
server, port = v[0], v[1]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user