package domain import ( "errors" "strings" "unicode" ) var hanmacSurnameRomanization = map[rune]string{ '한': "han", '김': "kim", '이': "lee", '박': "park", '최': "choi", '정': "jung", '조': "cho", '강': "kang", '윤': "yoon", '장': "jang", '임': "lim", '림': "lim", '신': "shin", '오': "oh", '서': "seo", '권': "kwon", '황': "hwang", '안': "ahn", '송': "song", '전': "jeon", '홍': "hong", '유': "yoo", '고': "ko", '문': "moon", '양': "yang", '손': "son", '배': "bae", '백': "baek", '허': "heo", '남': "nam", '심': "sim", '노': "noh", '하': "ha", '곽': "kwak", '성': "sung", '차': "cha", '주': "joo", '우': "woo", '구': "koo", '민': "min", '류': "ryu", '나': "na", '진': "jin", '지': "ji", '엄': "um", '채': "chae", '원': "won", '천': "cheon", '방': "bang", '공': "gong", '현': "hyun", '함': "ham", '여': "yeo", '추': "choo", '도': "do", '소': "so", '석': "seok", '선': "sun", '설': "seol", '마': "ma", '길': "gil", '연': "yeon", '위': "wi", '표': "pyo", '명': "myung", '기': "ki", '반': "ban", '라': "ra", '왕': "wang", '금': "geum", '옥': "ok", '육': "yook", '인': "in", '맹': "maeng", '제': "je", '모': "mo", '탁': "tak", '국': "guk", '어': "eo", '은': "eun", '편': "pyeon", '용': "yong", } var hanmacInitialRomanization = []string{ "g", "g", "n", "d", "d", "r", "m", "b", "b", "s", "s", "y", "j", "j", "c", "k", "t", "p", "h", } func SplitEmailDomain(email string) (string, string, error) { normalized := strings.ToLower(strings.TrimSpace(email)) before, after, ok := strings.Cut(normalized, "@") if !ok { return "", "", errors.New("email must contain @") } if strings.Count(normalized, "@") != 1 { return "", "", errors.New("email must contain one @") } localPart := strings.TrimSpace(before) domainPart := strings.TrimSpace(after) if domainPart == "" || !strings.Contains(domainPart, ".") { return "", "", errors.New("email domain is invalid") } return localPart, domainPart, nil } func ExtractNormalizedEmailLocalPart(email string) (string, error) { localPart, _, err := SplitEmailDomain(email) if err != nil { return "", err } if localPart == "" { return "", errors.New("email local-part is empty") } return localPart, nil } func BuildKoreanNameEmailBase(name string) (string, bool, error) { runes := compactNameRunes(name) if len(runes) < 2 { return "", true, nil } surname, ok := hanmacSurnameRomanization[runes[0]] if !ok { return "", true, nil } var builder strings.Builder for _, r := range runes[1:] { initial, ok := romanizedHangulInitial(r) if !ok { return "", true, nil } builder.WriteString(initial) } builder.WriteString(surname) return builder.String(), false, nil } func MatchesSuggestedNameRule(localPart string, base string) bool { localPart = strings.ToLower(strings.TrimSpace(localPart)) base = strings.ToLower(strings.TrimSpace(base)) if localPart == "" || base == "" { return false } if localPart == base { return true } if !strings.HasPrefix(localPart, base) { return false } suffix := localPart[len(base):] if suffix == "" { return false } for _, r := range suffix { if r < '0' || r > '9' { return false } } return true } func compactNameRunes(name string) []rune { var runes []rune for _, r := range strings.TrimSpace(name) { if unicode.IsSpace(r) { continue } runes = append(runes, r) } return runes } func romanizedHangulInitial(r rune) (string, bool) { const hangulBase = 0xAC00 const hangulEnd = 0xD7A3 if r < hangulBase || r > hangulEnd { return "", false } index := int(r-hangulBase) / 588 if index < 0 || index >= len(hanmacInitialRomanization) { return "", false } return hanmacInitialRomanization[index], true }