internal/utils/domain.go

package utils

import (
	"net"
	"strings"

	"golang.org/x/net/publicsuffix"
)

// GetBaseDomain returns the registered domain name for a given FQDN.
// It handles edge cases like dynamic hostnames registered under public suffixes
// (common with VPS providers like Linode, AWS, etc).
func GetBaseDomain(fqdn string) string {
	if fqdn == "" {
		return ""
	}

	// Remove trailing dot if present
	fqdn = strings.TrimSuffix(fqdn, ".")

	// If it's an IPv4 address, return it as is
	if ip := net.ParseIP(fqdn); ip != nil {
		if ip.To4() != nil {
			return fqdn
		}
	}

	domain, err := publicsuffix.EffectiveTLDPlusOne(fqdn)
	if err != nil {
		// Fallback for cases where EffectiveTLDPlusOne fails (e.g., "localhost")
		parts := strings.Split(fqdn, ".")
		if len(parts) >= 2 {
			return strings.Join(parts[len(parts)-2:], ".")
		}
		return fqdn
	}

	// If EffectiveTLDPlusOne returned the full FQDN, we're dealing with a
	// dynamic hostname registered under a public suffix (e.g., ip.linodeusercontent.com).
	// In this case, find the actual base domain by going one level above the public suffix.
	if domain == fqdn {
		suffix, _ := publicsuffix.PublicSuffix(fqdn)
		if suffix != "" && suffix != fqdn {
			// Get the domain one level above the suffix
			// e.g., for suffix "ip.linodeusercontent.com", find "linodeusercontent.com"
			suffixParts := strings.Split(suffix, ".")
			if len(suffixParts) >= 2 {
				return strings.Join(suffixParts[len(suffixParts)-2:], ".")
			}
		}
	}

	return domain
}