package main import ( // Standard "fmt" "maps" "slices" "strings" ) type DNSRecord struct { ID string `json:".id"` Address string Disabled string Dynamic string Name string TTL string Type string } type DomainPart struct { Subparts map[string]*DomainPart `json:",omitempty"` } type RecordsTree struct { Record DNSRecord Children []RecordsTree } func SortDNSRecord(a, b DNSRecord) int { aComponents := strings.Split(a.Name, ".") bComponents := strings.Split(b.Name, ".") slices.Reverse(aComponents) slices.Reverse(bComponents) for i, aComp := range aComponents { if i >= len(bComponents) { return -1 } bComp := bComponents[i] if aComp > bComp { return 1 } if aComp < bComp { return -1 } } return 0 } func (r DNSRecord) Parts() int { return len(strings.Split(r.Name, ".")) } func (r DNSRecord) Part(numParts int) string { splitName := strings.Split(r.Name, ".") slices.Reverse(splitName) parts := []string{} for i := range numParts { if i >= len(splitName) { break } parts = append(parts, splitName[i]) } slices.Reverse(parts) return strings.Join(parts, ".") } func (r DNSRecord) NameReversed() string { parts := strings.Split(r.Name, ".") slices.Reverse(parts) return strings.Join(parts, ".") } func BuildRecordsTree(records []DNSRecord) *DomainPart { topPart := new(DomainPart) topPart.Subparts = make(map[string]*DomainPart) for _, record := range records { curPart := topPart currentDomainNameSplit := strings.Split(record.Name, ".") slices.Reverse(currentDomainNameSplit) for _, part := range currentDomainNameSplit { if nextDomainPart, found := curPart.Subparts[part]; !found { newPart := new(DomainPart) newPart.Subparts = make(map[string]*DomainPart) curPart.Subparts[strings.ToLower(part)] = newPart curPart = newPart } else { curPart = nextDomainPart } } } return topPart } type HTMLElement struct { Header bool HTML string } func (dp *DomainPart) ToHTMLElements(parts []string, idFrom int) []HTMLElement { var lines []HTMLElement sortedParts := slices.Sorted(maps.Keys(dp.Subparts)) for i, part := range sortedParts { subpart := dp.Subparts[part] newParts := append(parts, part) reversedParts := make([]string, len(newParts)) copy(reversedParts, newParts) slices.Reverse(reversedParts) fqdn := strings.Join(reversedParts, ".") mostSpecificPart := reversedParts[0] restPart := "" if len(reversedParts) > 1 { restPart = strings.Join(reversedParts[1:], ".") mostSpecificPart += "." } if len(subpart.Subparts) == 0 { html := fmt.Sprintf( `