1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
package shared

import (
	"bytes"
	"errors"
	"fmt"
	"net/url"
	"strings"
	"unicode"
)

const MaxDescriptionLen = 256

func GetHostName(userUrl string) (string, error) {
	var parsedUrl *url.URL
	var urlError error
	parsedUrl, urlError = url.Parse(userUrl)
	if urlError != nil {
		return "", fmt.Errorf("Failed to parse user URL '%s': %v", userUrl, urlError)
	}
	return parsedUrl.Hostname(), nil
}

func MakeFullMoniker(hostName, handle string) string {
	return "@" + handle + "@" + hostName
}

func GetNameWithParrot(name string) string {
	return "🦜 " + name
}

func TruncateWithEllipsis(text string, maxLen int) string {
	if len(text) <= maxLen {
		return text
	}
	// https://stackoverflow.com/a/73939904/7479498
	lastSpaceIx := maxLen
	len := 0
	for i, r := range text {
		if unicode.IsSpace(r) {
			lastSpaceIx = i
		}
		len++
		if len > maxLen {
			return text[:lastSpaceIx] + "…"
		}
	}
	// If here, string is shorter or equal to maxLen
	return text
}

func ValidateHandle(handle string) error {
	if len(handle) == 0 {
		return errors.New("parrot handle cannot be empty")
	}
	var nDots, nNonDots, nUpper int
	for _, c := range handle {
		if unicode.IsUpper(c) {
			nUpper++
		}
		if c == '.' {
			nDots++
		} else {
			nNonDots++
		}
	}
	if nDots == 0 {
		return errors.New("parrot handle must have at least one dot")
	}
	if nNonDots < 2 {
		return errors.New("parrot handle must have at least two non-dots")
	}
	if nUpper != 0 {
		return errors.New("parrot handle must not have upper-case letters")
	}
	return nil
}

func GetHandleFromUrl(url string) string {

	url = strings.TrimPrefix(url, "http://")
	url = strings.TrimPrefix(url, "https://")
	url = strings.TrimRight(url, "/")

	var buf bytes.Buffer
	for i := 0; i < len(url); i++ {
		c := url[i]
		if c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '-' || c == '.' {
			buf.WriteByte(c)
		} else {
			buf.WriteString(".")
		}
	}
	res := strings.ToLower(buf.String())

	for {
		merged := strings.ReplaceAll(res, "..", ".")
		if len(merged) == len(res) {
			break
		}
		res = merged
	}
	return res
}