package whois import ( "strings" "time" ) func parse(domain string, result string) (Result, error) { ext := getExtension(domain) var data Result var err error switch ext { case "cn": data, err = dotCNParser(domain, result) case "jp": 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, } 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 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 } } } 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:")) } if strings.HasPrefix(line, "Registry Domain ID:") { res.domainID = strings.TrimSpace(strings.TrimPrefix(line, "Registry Domain ID:")) } if strings.HasPrefix(line, "Updated Date:") { tmpDate := parseDate(strings.TrimSpace(strings.TrimPrefix(line, "Updated Date:"))) if !tmpDate.IsZero() { res.updateDate = tmpDate } } if strings.HasPrefix(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:") { 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:")) } 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{}{} } if strings.HasPrefix(line, "Name Server:") { res.nsServers = append(res.nsServers, strings.TrimSpace(strings.TrimPrefix(line, "Name Server:"))) } if strings.HasPrefix(line, "DNSSEC:") { res.dnssec = strings.TrimSpace(strings.TrimPrefix(line, "DNSSEC:")) } if strings.HasPrefix(line, "Registrant Name:") { r.Name = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Name:")) } if strings.HasPrefix(line, "Registrant Organization:") { r.Org = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Organization:")) } if strings.HasPrefix(line, "Registrant Street:") { r.Addr = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Street:")) } if strings.HasPrefix(line, "Registrant City:") { r.City = strings.TrimSpace(strings.TrimPrefix(line, "Registrant City:")) } if strings.HasPrefix(line, "Registrant State/Province:") { r.State = strings.TrimSpace(strings.TrimPrefix(line, "Registrant State/Province:")) } if strings.HasPrefix(line, "Registrant Postal Code:") { r.Zip = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Postal Code:")) } if strings.HasPrefix(line, "Registrant Country:") { r.Country = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Country:")) } if strings.HasPrefix(line, "Registrant Phone:") { r.Phone = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Phone:")) } if strings.HasPrefix(line, "Registrant Phone Ext:") { r.PhoneExt = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Phone Ext:")) } if strings.HasPrefix(line, "Registrant Fax:") { r.Fax = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Fax:")) } if strings.HasPrefix(line, "Registrant Fax Ext:") { r.FaxExt = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Fax Ext:")) } if strings.HasPrefix(line, "Registrant Email:") { r.Email = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Email:")) } if strings.HasPrefix(line, "Admin Name:") { a.Name = strings.TrimSpace(strings.TrimPrefix(line, "Admin Name:")) } if strings.HasPrefix(line, "Admin Organization:") { a.Org = strings.TrimSpace(strings.TrimPrefix(line, "Admin Organization:")) } if strings.HasPrefix(line, "Admin Street:") { a.Addr = strings.TrimSpace(strings.TrimPrefix(line, "Admin Street:")) } if strings.HasPrefix(line, "Admin City:") { a.City = strings.TrimSpace(strings.TrimPrefix(line, "Admin City:")) } if strings.HasPrefix(line, "Admin State/Province:") { a.State = strings.TrimSpace(strings.TrimPrefix(line, "Admin State/Province:")) } if strings.HasPrefix(line, "Admin Postal Code:") { a.Zip = strings.TrimSpace(strings.TrimPrefix(line, "Admin Postal Code:")) } if strings.HasPrefix(line, "Admin Country:") { a.Country = strings.TrimSpace(strings.TrimPrefix(line, "Admin Country:")) } if strings.HasPrefix(line, "Admin Phone:") { a.Phone = strings.TrimSpace(strings.TrimPrefix(line, "Admin Phone:")) } if strings.HasPrefix(line, "Admin Phone Ext:") { a.PhoneExt = strings.TrimSpace(strings.TrimPrefix(line, "Admin Phone Ext:")) } if strings.HasPrefix(line, "Admin Fax:") { a.Fax = strings.TrimSpace(strings.TrimPrefix(line, "Admin Fax:")) } if strings.HasPrefix(line, "Admin Fax Ext:") { a.FaxExt = strings.TrimSpace(strings.TrimPrefix(line, "Admin Fax Ext:")) } if strings.HasPrefix(line, "Admin Email:") { a.Email = strings.TrimSpace(strings.TrimPrefix(line, "Admin Email:")) } if strings.HasPrefix(line, "Tech Name:") { t.Name = strings.TrimSpace(strings.TrimPrefix(line, "Tech Name:")) } if strings.HasPrefix(line, "Tech Organization:") { t.Org = strings.TrimSpace(strings.TrimPrefix(line, "Tech Organization:")) } if strings.HasPrefix(line, "Tech Street:") { t.Addr = strings.TrimSpace(strings.TrimPrefix(line, "Tech Street:")) } if strings.HasPrefix(line, "Tech City:") { t.City = strings.TrimSpace(strings.TrimPrefix(line, "Tech City:")) } if strings.HasPrefix(line, "Tech State/Province:") { t.State = strings.TrimSpace(strings.TrimPrefix(line, "Tech State/Province:")) } if strings.HasPrefix(line, "Tech Postal Code:") { t.Zip = strings.TrimSpace(strings.TrimPrefix(line, "Tech Postal Code:")) } if strings.HasPrefix(line, "Tech Country:") { t.Country = strings.TrimSpace(strings.TrimPrefix(line, "Tech Country:")) } if strings.HasPrefix(line, "Tech Phone:") { t.Phone = strings.TrimSpace(strings.TrimPrefix(line, "Tech Phone:")) } if strings.HasPrefix(line, "Tech Phone Ext:") { t.PhoneExt = strings.TrimSpace(strings.TrimPrefix(line, "Tech Phone Ext:")) } if strings.HasPrefix(line, "Tech Fax:") { t.Fax = strings.TrimSpace(strings.TrimPrefix(line, "Tech Fax:")) } if strings.HasPrefix(line, "Tech Fax Ext:") { t.FaxExt = strings.TrimSpace(strings.TrimPrefix(line, "Tech Fax Ext:")) } if strings.HasPrefix(line, "Tech Email:") { t.Email = strings.TrimSpace(strings.TrimPrefix(line, "Tech Email:")) } } for status := range statusMap { res.statusRaw = append(res.statusRaw, status) } res.registerInfo = r res.adminInfo = a res.techInfo = t 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, rawData: data, } var r PersonalInfo if strings.HasPrefix("No matching record.", strings.TrimSpace(data)) { 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") for _, line := range split { line = strings.TrimSpace(line) if strings.HasPrefix(line, "Domain Name:") { res.nsServers = []string{} res.domain = strings.TrimSpace(strings.TrimPrefix(line, "Domain Name:")) } if strings.HasPrefix(line, "ROID:") { res.domainID = strings.TrimSpace(strings.TrimPrefix(line, "ROID:")) } if strings.HasPrefix(line, "Registration Time:") { res.registerDate = parseCNDate(strings.TrimSpace(strings.TrimPrefix(line, "Registration Time:"))) } if strings.HasPrefix(line, "Expiration Time:") { res.expireDate = parseCNDate(strings.TrimSpace(strings.TrimPrefix(line, "Expiration Time:"))) } if strings.HasPrefix(line, "Sponsoring Registrar:") { res.registar = strings.TrimSpace(strings.TrimPrefix(line, "Sponsoring Registrar:")) } if strings.HasPrefix(line, "Status:") { statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Status:")), " ")[0]] = struct{}{} } if strings.HasPrefix(line, "Domain Status:") { statusMap[strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "Domain 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, "DNSSEC:") { res.dnssec = strings.TrimSpace(strings.TrimPrefix(line, "DNSSEC:")) } if strings.HasPrefix(line, "Registrant:") { r.Name = strings.TrimSpace(strings.TrimPrefix(line, "Registrant:")) } if strings.HasPrefix(line, "Registrant Contact Email:") { r.Email = strings.TrimSpace(strings.TrimPrefix(line, "Registrant Contact Email:")) } } for status := range statusMap { res.statusRaw = append(res.statusRaw, status) } res.registerInfo = r return res, nil } func dotJPParser(domain, data string) (Result, error) { var res = Result{ domain: domain, rawData: data, } var r PersonalInfo split := strings.Split(data, "\n") startAddress := false for _, line := range split { if strings.HasPrefix(line, "No match!!") { res.exists = false return res, nil } 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]")) } if strings.HasPrefix(line, "[登録者名]") { r.Name = strings.TrimSpace(strings.TrimPrefix(line, "[登録者名]")) } if strings.HasPrefix(line, "[Name Server]") { res.nsServers = append(res.nsServers, strings.TrimSpace(strings.TrimPrefix(line, "[Name Server]"))) } if strings.HasPrefix(line, "[状態]") { res.statusRaw = append(res.statusRaw, strings.TrimSpace(strings.TrimPrefix(line, "[状態]"))) } if strings.HasPrefix(line, "[ロック状態]") { res.statusRaw = append(res.statusRaw, strings.TrimSpace(strings.TrimPrefix(line, "[ロック状態]"))) } if strings.HasPrefix(line, "[登録年月日]") { res.registerDate = parseJPDate(strings.TrimSpace(strings.TrimPrefix(line, "[登録年月日]")), true) } if strings.HasPrefix(line, "[最終更新]") { res.updateDate = parseJPDate(strings.TrimSpace(strings.TrimPrefix(line, "[最終更新]")), false) } if strings.HasPrefix(line, "[有効期限]") { res.expireDate = parseJPDate(strings.TrimSpace(strings.TrimPrefix(line, "[有効期限]")), true) } if strings.HasPrefix(line, "[名前]") { r.Name = strings.TrimSpace(strings.TrimPrefix(line, "[名前]")) } if strings.HasPrefix(line, "[組織名]") { r.Org = strings.TrimSpace(strings.TrimPrefix(line, "[組織名]")) } if strings.HasPrefix(line, "[Email]") { r.Email = strings.TrimSpace(strings.TrimPrefix(line, "[Email]")) } if strings.HasPrefix(line, "[住所]") { r.Addr = strings.TrimSpace(strings.TrimPrefix(line, "[住所]")) continue } if strings.HasPrefix(line, "[Postal Address]") { startAddress = false continue } if startAddress { r.Addr += "\n" + line } if strings.HasPrefix(line, "[電話番号]") { r.Phone = strings.TrimSpace(strings.TrimPrefix(line, "[電話番号]")) } if strings.HasPrefix(line, "[FAX番号]") { r.Fax = strings.TrimSpace(strings.TrimPrefix(line, "[FAX番号]")) break } } res.registerInfo = r return res, nil } func dotTWParser(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 strings.HasPrefix(line, "No Found") || strings.HasPrefix(line, "網域名稱不合規定") { 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, "Registration Service Provider:") { startNs = false res.registar = strings.TrimSpace(strings.TrimPrefix(line, "Registration Service Provider:")) } if strings.HasPrefix(line, "Record created on") { res.registerDate = parseCNDate(strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(line, "Record created on"), "(UTC+8)"))) } if strings.HasPrefix(line, "Record expires on") { res.expireDate = parseCNDate(strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(line, "Record expires on"), "(UTC+8)"))) } if strings.HasPrefix(line, "Domain Status:") { res.statusRaw = append(res.statusRaw, strings.TrimSpace(strings.TrimPrefix(line, "Domain Status:"))) } if strings.HasPrefix(line, "Domain servers in listed order:") { startNs = true continue } if strings.HasPrefix(line, "Registrant:") { currentStatus = 1 startIdx = idx p = PersonalInfo{} continue } if currentStatus > 0 { if line == "(Redacted for privacy)" { switch currentStatus { case 1: r = p case 2: a = p case 3: t = p } continue } switch idx - startIdx { case 1: p.Name = line case 3: p.Email = line case 4: p.Country = line } } if startNs { res.nsServers = append(res.nsServers, line) } } res.registerInfo = r res.adminInfo = a res.techInfo = t 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, 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 } func parseCNDate(date string) time.Time { t, _ := time.ParseInLocation("2006-01-02 15:04:05", date, time.FixedZone("CST", 8*3600)) t = t.In(time.Local) return t } func parseJPDate(date string, onlyMD bool) time.Time { if onlyMD { t, _ := time.ParseInLocation("2006/01/02", date, time.FixedZone("JST", 9*3600)) t = t.In(time.Local) return t } t, _ := time.ParseInLocation("2006/01/02 15:04:05 (JST)", date, time.FixedZone("JST", 9*3600)) 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 }