package main import ( "flag" "fmt" "math/rand" "strings" "time" "unicode" ) var ( syllables = []string{ "ka", "lo", "mi", "te", "sa", "ri", "zu", "ve", "po", "ni", "fa", "go", "bi", "du", "ze", "wi", "la", "mo", "si", "ta", "chi", "so", "ki", "ma", "ha", "yu", "tsu", "ko", "na", "fu", "mi", "ya", "to", "hi", "su", "no", "ra", "se", "ku", "me", "el", "ar", "is", "on", "vi", "lu", "ce", "ra", "di", "vo", "ti", "re", "ca", "li", "pe", "co", "mu", "ne", "si", "la", "skal", "vorn", "dre", "thor", "sig", "fre", "bjorn", "ulf", "ragn", "skol", "grim", "tor", "val", "hild", "sven", "lok", "frig", "od", "run", "skir", "bri", "cen", "lor", "ael", "wyn", "fion", "dea", "mor", "cai", "lyn", "glen", "row", "sev", "bran", "cer", "dru", "fin", "gwen", "lir", "mae", "za", "nur", "sal", "jam", "far", "lay", "ami", "rah", "sah", "nad", "mal", "yas", "zin", "bah", "qas", "hil", "ram", "sul", "zar", "mun", "vla", "mir", "sto", "dre", "bor", "slav", "rad", "mil", "ziv", "gor", "dan", "luk", "pet", "nik", "sov", "yar", "zol", "kras", "vit", "bog", "nde", "kwe", "zuri", "oba", "chi", "tum", "san", "yem", "fol", "dji", "bwe", "kud", "mal", "ngo", "sia", "tan", "waz", "yol", "zim", "kwa", "dev", "sri", "jai", "anu", "raj", "pri", "san", "vid", "kir", "ran", "ash", "vik", "dip", "man", "sur", "tar", "neh", "par", "jit", "sam", "theo", "nyx", "eos", "zir", "phi", "rho", "kai", "zel", "ion", "pyr", "hel", "tha", "cri", "lys", "dor", "xan", "nym", "pol", "ath", "zen", "moa", "lua", "kai", "nalu", "hina", "mana", "tane", "rua", "vai", "lea", "wald", "grim", "hart", "stein", "burg", "feld", "wolf", "brand", "helm", "sieg", "ay", "gul", "tur", "khan", "sel", "yur", "tem", "bar", "oz", "alp", } words = []string{ "sky", "leaf", "stone", "cloud", "river", "moon", "wind", "tree", "hill", "dawn", "mist", "vale", "ridge", "bloom", "shade", "wave", "pine", "oak", "fern", "lake", "dune", "brook", "frost", "glen", "tide", "cove", "reef", "snow", "breeze", "field", "sand", "peak", "wood", "stream", "bay", "crag", "pond", "marsh", "cliff", "mead", "spruce", "cedar", "vine", "moss", "thorn", "birch", "ash", "elm", "heath", "gorge", "dream", "echo", "spark", "flow", "haze", "gleam", "pulse", "vibe", "dusk", "hope", "calm", "glow", "whisper", "drift", "flicker", "muse", "soul", "void", "quest", "fate", "bliss", "surge", "glee", "trust", "peace", "spirit", "charm", "vision", "awe", "grace", "clarity", "essence", "radiance", "serenity", "mirth", "zest", "bloom", "luster", "shade", "gleam", "sparkle", "wisp", "nexus", "vapor", "glee", "mood", "scent", "breeze", "tide", "key", "flame", "path", "crown", "forge", "veil", "spire", "gem", "lock", "chain", "lamp", "coin", "blade", "ring", "scroll", "torch", "bell", "horn", "vase", "cloak", "shield", "spear", "flag", "book", "gate", "mirror", "staff", "wand", "chest", "map", "drum", "quill", "rope", "wheel", "hook", "lens", "knot", "pipe", "cup", "bowl", "plate", "knife", "rod", "candle", "locket", "pendant", "banner", "beacon", "forge", "loom", "nova", "orbit", "luna", "comet", "star", "galaxy", "nebula", "cosmo", "pulse", "ray", "quasar", "meteor", "sun", "void", "eclipse", "astro", "light", "dawn", "dusk", "sky", "flare", "crater", "dust", "ring", "belt", "moon", "tide", "glint", "beam", "spark", "cluster", "void", "halo", "arc", "zenith", "nadir", "sky", "luster", "gleam", "vapor", "corona", "umbra", "penumbra", "aurora", "cosmos", "spire", "vortex", "nebula", "pulsar", "orbit", "nyx", "zephyr", "aura", "titan", "phoenix", "siren", "griffin", "hydra", "minos", "atlas", "hera", "zeus", "odin", "thor", "loki", "freya", "cronos", "ares", "muse", "fury", "apollo", "artemis", "prometheus", "helios", "selene", "pan", "echo", "nereus", "psyche", "eros", "orion", "hermes", "hades", "persephone", "dionysus", "athena", "hector", "achilles", "triton", "nymph", "centaur", "satyr", "medusa", "cerberus", "chimera", "pegasus", "icarus", "daedalus", "midgard", "valhalla", "joy", "hope", "fear", "love", "rage", "calm", "glee", "sorrow", "trust", "pride", "bliss", "awe", "grief", "zeal", "peace", "lust", "wrath", "cheer", "dread", "gleam", "mirth", "gloom", "fervor", "ease", "fury", "spark", "zest", "muse", "thrill", "calm", "ardor", "glee", "woe", "rapture", "vibe", "pang", "blaze", "whisper", "pulse", "dream", "delight", "sigh", "yearn", "mood", "spirit", "surge", "charm", "elation", "serenity", "vigor", "azure", "crimson", "emerald", "amber", "violet", "ruby", "sapphire", "onyx", "jade", "gold", "silver", "ivory", "ebony", "coral", "topaz", "pearl", "garnet", "opal", "turquoise", "amethyst", "bronze", "copper", "sienna", "indigo", "vermilion", "ochre", "saffron", "mauve", "lavender", "teal", "maroon", "cerulean", "cobalt", "sepia", "magenta", "cyan", "olive", "taupe", "rose", "lilac", "umber", "sable", "chartreuse", "vermilion", "puce", "fuchsia", "aqua", "bistre", "sage", "mint", "fire", "water", "earth", "air", "stone", "ice", "storm", "flame", "tide", "mist", "wind", "soil", "sky", "snow", "ash", "clay", "rock", "wave", "dust", "fog", "blaze", "stream", "breeze", "frost", "sand", "magma", "vapor", "spark", "glint", "surge", "quartz", "ember", "gust", "silt", "rubble", "dew", "spray", "rift", "smoke", "foam", "gale", "cinder", "ore", "salt", "soot", "gravel", "slag", "haze", "ridge", "crust", } modifiers = []string{ "neo", "ix", "al", "en", "ora", "is", "yn", "io", "za", "qu", "ex", "um", "an", "er", "os", "ad", "il", "or", "es", "ys", "ax", "on", "et", "im", "us", "id", "ox", "em", "ar", "un", "ol", "az", "ir", "ov", "ut", "av", "ez", "om", "in", "ep", "as", "iz", "ed", "up", "at", "it", "ef", "ag", "am", "oc", "byte", "code", "link", "sys", "net", "tech", "data", "grid", "bit", "wave", "hack", "node", "port", "chip", "flux", "core", "sync", "pulse", "lan", "web", "byte", "scan", "loop", "disk", "ram", "mod", "algo", "hash", "ping", "boot", "cache", "link", "wire", "bolt", "spark", "flow", "beam", "drive", "glitch", "frame", "pixel", "voxel", "quantum", "circuit", "relay", "signal", "stream", "cloud", "cyber", "nano", "zen", "vox", "lux", "syn", "arc", "haze", "gleam", "flow", "dusk", "mist", "void", "spark", "echo", "drift", "aura", "soul", "whisper", "flicker", "bliss", "calm", "pulse", "vibe", "shade", "bloom", "surge", "glee", "trust", "peace", "spirit", "charm", "vision", "awe", "grace", "clarity", "essence", "radiance", "serenity", "mirth", "zest", "luster", "dream", "hope", "muse", "wisp", "vapor", "gleam", "sparkle", "mood", "scent", "breeze", "kai", "ren", "sol", "mir", "xu", "yul", "zin", "rah", "sah", "jam", "far", "lay", "ami", "nad", "bah", "qas", "hil", "ram", "sul", "zar", "tal", "nur", "jem", "sal", "yaz", "khal", "zara", "nuri", "sami", "hana", "ravi", "sana", "tari", "zain", "lila", "maya", "raj", "sri", "dev", "jai", "anu", "kir", "vid", "ash", "vik", "dip", "man", "sur", "tar", "neh", "cryo", "plex", "nova", "zeta", "omni", "cyon", "lith", "quark", "ion", "nexus", "volt", "pulse", "beam", "holo", "grid", "flux", "core", "spire", "link", "wave", "chrono", "synth", "neo", "arc", "vox", "lume", "zoid", "micron", "photon", "plasma", "cyber", "nano", "omega", "sigma", "delta", "theta", "gamma", "epsilon", "lambda", "mu", "rho", "tau", "phi", "psi", "chi", "iota", "kappa", "beta", "alpha", "omicron", "verse", "tale", "saga", "epic", "rune", "myth", "fable", "ode", "lyric", "prose", "sonnet", "ballad", "poem", "stanza", "rhyme", "epos", "lay", "saga", "yarn", "lore", "canticle", "elegy", "psalm", "hymn", "chant", "fable", "mythos", "legend", "parable", "story", "novella", "epic", "ode", "verse", "rune", "tale", "saga", "lyric", "prose", "ballad", "sonnet", "poem", "stanza", "rhyme", "epos", "lay", "yarn", "lore", "canticle", "elegy", "note", "chord", "tune", "beat", "rhythm", "mel", "song", "vibe", "harmony", "tempo", "pitch", "scale", "key", "tone", "cadence", "lilt", "hum", "riff", "melody", "verse", "chorus", "bridge", "hook", "strain", "bar", "meter", "pulse", "flow", "swing", "jazz", "blues", "rock", "pop", "folk", "soul", "funk", "reggae", "samba", "tango", "waltz", "sonata", "fugue", "prelude", "coda", "aria", "rondo", "symphony", "ballad", "chant", "hymn", } vowels = []string{ "a", "e", "i", "o", "u", "ai", "ou", "ae", "ei", "oa", "au", "ie", "ue", "oi", "ui", "ea", "eo", "io", "ua", "ay", "ao", "eu", "iu", "oy", "ya", "ye", "yo", "yu", } consonants = []string{ "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "v", "w", "y", "z", "sh", "ch", "th", "ph", "kr", "sl", "br", "tr", "kl", "gr", "fl", "pr", "dr", "sk", "sm", "sn", "sp", "st", "sw", "bl", "cl", "fr", "gl", "pl", "sc", "tw", "wh", "zh", "qu", } ) func GenerateUsername(minLength, maxLength int, noNumbers, noCamelCase bool) string { rand.Seed(time.Now().UnixNano() ^ int64(rand.Int())) var username strings.Builder separators := []string{"-", "_"} separator := separators[rand.Intn(len(separators))] strategy := rand.Intn(5) switch strategy { case 0: numSyllables := rand.Intn(3) + 2 for i := 0; i < numSyllables; i++ { syllable := syllables[rand.Intn(len(syllables))] if rand.Float32() < 0.4 { syllable = strings.Title(syllable) } username.WriteString(syllable) if i < numSyllables-1 && rand.Float32() < 0.2 { username.WriteString(separator) } } case 1: word := words[rand.Intn(len(words))] if rand.Float32() < 0.5 { word = strings.Title(word) } username.WriteString(word) if rand.Float32() < 0.6 { modifier := modifiers[rand.Intn(len(modifiers))] if rand.Float32() < 0.5 { modifier = strings.Title(modifier) } username.WriteString(modifier) } else { syllable := syllables[rand.Intn(len(syllables))] if rand.Float32() < 0.5 { syllable = strings.Title(syllable) } username.WriteString(syllable) } case 2: length := rand.Intn(4) + 3 for i := 0; i < length; i++ { if i%2 == 0 && rand.Float32() < 0.7 { username.WriteString(consonants[rand.Intn(len(consonants))]) } else { username.WriteString(vowels[rand.Intn(len(vowels))]) } } if rand.Float32() < 0.4 { result := username.String() if len(result) > 0 { runes := []rune(result) runes[0] = unicode.ToUpper(runes[0]) username = strings.Builder{} username.WriteString(string(runes)) } } case 3: components := []string{ syllables[rand.Intn(len(syllables))], words[rand.Intn(len(words))], modifiers[rand.Intn(len(modifiers))], } rand.Shuffle(len(components), func(i, j int) { components[i], components[j] = components[j], components[i] }) numComponents := rand.Intn(2) + 2 for i := 0; i < numComponents; i++ { comp := components[i] if rand.Float32() < 0.5 { comp = strings.Title(comp) } username.WriteString(comp) if i < numComponents-1 && rand.Float32() < 0.2 { username.WriteString(separator) } } case 4: length := rand.Intn(5) + 4 pattern := rand.Intn(3) for i := 0; i < length; i++ { if pattern == 0 { if i%2 == 0 { username.WriteString(consonants[rand.Intn(len(consonants))]) } else { username.WriteString(vowels[rand.Intn(len(vowels))]) } } else if pattern == 1 { if rand.Float32() < 0.6 { username.WriteString(vowels[rand.Intn(len(vowels))]) } else { username.WriteString(consonants[rand.Intn(len(consonants))]) } } else { if rand.Float32() < 0.6 { username.WriteString(consonants[rand.Intn(len(consonants))]) } else { username.WriteString(vowels[rand.Intn(len(vowels))]) } } } if !noCamelCase && rand.Float32() < 0.3 { result := username.String() words := strings.Split(result, "") for i := range words { if rand.Float32() < 0.2 { words[i] = strings.Title(words[i]) } } username = strings.Builder{} username.WriteString(strings.Join(words, "")) } } if !noNumbers && rand.Float32() < 0.05 { num := rand.Intn(100) username.WriteString(fmt.Sprintf("%02d", num)) } if rand.Float32() < 0.05 { result := username.String() if strings.Contains(result, "a") { result = strings.Replace(result, "a", "ae", 1) username = strings.Builder{} username.WriteString(result) } } result := username.String() if len(result) < minLength || len(result) > maxLength { return GenerateUsername(minLength, maxLength, noNumbers, noCamelCase) } lowerResult := strings.ToLower(result) for _, word := range words { if lowerResult == word { return GenerateUsername(minLength, maxLength, noNumbers, noCamelCase) } } if rand.Float32() < 0.1 { result = strings.Replace(result, "-", ".", 1) result = strings.Replace(result, "_", ".", 1) } return result } func main() { minLength := flag.Int("min-length", 8, "minimum username length") maxLength := flag.Int("max-length", 12, "maximum username length") noNumbers := flag.Bool("no-numbers", false, "disable appending numbers") noCamelCase := flag.Bool("no-camelcase", false, "disable camelCase styling") count := flag.Int("count", 10, "number of usernames to generate") flag.Parse() if *minLength > *maxLength { fmt.Println("[err] min-length cannot be greater than max-length") return } if *count <= 0 { fmt.Println("[err] count must be positive") return } for i := 0; i < *count; i++ { fmt.Println(GenerateUsername(*minLength, *maxLength, *noNumbers, *noCamelCase)) } }