From b3f81add0eb27cd46b81e89be07c97b77325d52c Mon Sep 17 00:00:00 2001 From: samosvalishe Date: Mon, 18 May 2026 17:51:27 +0300 Subject: [PATCH] =?UTF-8?q?refactor:=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20namegen=20=D0=B2=20internal-=D0=BF=D0=B0=D0=BA?= =?UTF-8?q?=D0=B5=D1=82,=20=D1=80=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D1=83=D0=BB=D1=8B=20=D0=B8=D0=BC=D1=91?= =?UTF-8?q?=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Перенос client/namegen.go в client/internal/namegen с экспортируемым Generate() - Вынос данных имён в data/*.txt, загрузка через //go:embed - Расширение пулов: мужские 729→760, женские 31→99, фамилии 60→286 (вкл. мем-имена) - Переписан feminizeSurname через []rune (убрана хрупкая байтовая арифметика на len-4) - Переход с math/rand на math/rand/v2 - Юнит-тесты: parseLines, feminizeSurname, целостность пулов, форма и покрытие по полу у Generate --- .../namegen/data/first_names_female.txt | 99 ++ .../namegen/data/first_names_male.txt | 760 +++++++++++++++ client/internal/namegen/data/last_names.txt | 286 ++++++ client/internal/namegen/namegen.go | 80 ++ client/internal/namegen/namegen_test.go | 162 ++++ client/main.go | 3 +- client/namegen.go | 883 ------------------ 7 files changed, 1389 insertions(+), 884 deletions(-) create mode 100644 client/internal/namegen/data/first_names_female.txt create mode 100644 client/internal/namegen/data/first_names_male.txt create mode 100644 client/internal/namegen/data/last_names.txt create mode 100644 client/internal/namegen/namegen.go create mode 100644 client/internal/namegen/namegen_test.go delete mode 100644 client/namegen.go diff --git a/client/internal/namegen/data/first_names_female.txt b/client/internal/namegen/data/first_names_female.txt new file mode 100644 index 0000000..68fc996 --- /dev/null +++ b/client/internal/namegen/data/first_names_female.txt @@ -0,0 +1,99 @@ +Александра +Алина +Алла +Алёна +Анастасия +Ангелина +Анна +Антонина +Валентина +Валерия +Варвара +Василиса +Вера +Вероника +Виктория +Галина +Дарина +Дарья +Диана +Ева +Евгения +Екатерина +Елена +Елизавета +Зинаида +Зоя +Инна +Ирина +Карина +Кира +Кристина +Ксения +Лариса +Лидия +Любовь +Людмила +Майя +Маргарита +Марина +Мария +Милана +Надежда +Наталья +Нина +Олеся +Ольга +Полина +Раиса +Регина +Римма +Светлана +София +Тамара +Татьяна +Ульяна +Эльвира +Юлия +Яна +Ярослава +Аврора +Алиса +Арья +Барби +Беллатриса +Белль +Ванда +Венди +Гамора +Гермиона +Гоар +Дейенерис +Дороти +Жасмин +Зена +Круэлла +Лара +Лея +Луна +Малефисента +Маша +Матильда +Мерида +Минни +Молли +Мона +Мулан +Наташа +Пиппи +Рапунцель +Санса +Серсея +Тиана +Тинкер +Тринити +Урсула +Фиона +Харли +Эдна +Эльза diff --git a/client/internal/namegen/data/first_names_male.txt b/client/internal/namegen/data/first_names_male.txt new file mode 100644 index 0000000..db0caf2 --- /dev/null +++ b/client/internal/namegen/data/first_names_male.txt @@ -0,0 +1,760 @@ +Аарон +Аба +Аббас +Абд аль-Узза +Абдуллах +Абид +Аботур +Аввакум +Август +Авдей +Авель +Аверкий +Авигдор +Авирмэд +Авксентий +Авл +Авнер +Аврелий +Автандил +Автоном +Агапит +Агафангел +Агафодор +Агафон +Аги +Агриппа +Адам +Адар +Адиль +Адольф +Адонирам +Адриан +Азамат +Азарий +Азат +Азиз +Азим +Айварс +Айдар +Айрат +Акакий +Аквилий +Акиф +Акоп +Аксель +Алан +Аланус +Алек +Александр +Алексей +Алемдар +Алик +Алим +Алипий +Алишер +Алмат +Алоиз +Алон +Альберик +Альберт +Альбин +Альваро +Альвиан +Альвизе +Альфонс +Альфред +Амадис +Амвросий +Амедей +Амин +Амир +Амр +Амфилохий +Анания +Анас +Анастасий +Анатолий +Ангеляр +Андокид +Андрей +Андроник +Аннерс +Анри +Ансельм +Антипа +Антон +Антоний +Антонин +Антуан +Арам +Арефа +Арзуман +Аристарх +Аристон +Ариф +Аркадий +Арсений +Артём +Артур +Арфаксад +Асаф +Атанасий +Атом +Аттик +Афанасий +Афинагор +Афиней +Афиф +Африкан +Ахилл +Ахмад +Ахтям +Ашот +Бадар +Бартоломео +Басир +Бахтияр +Баян +Безсон +Бен +Беньямин +Берт +Бехруз +Билял +Богдан +Болеслав +Бонавентура +Борис +Борислав +Боян +Бронислав +Брячислав +Бурхан +Бутрос +Бямбасурэн +Вадим +Валентин +Валентино +Валерий +Валерьян +Вальдемар +Вангьял +Варлам +Варнава +Варфоломей +Василий +Вахтанг +Велвел +Венансио +Венедикт +Вениамин +Венцеслав +Вигго +Викентий +Виктор +Викторин +Вильгельм +Винцас +Виссарион +Виталий +Витаутас +Вито +Владимир +Владислав +Владлен +Влас +Воислав +Володарь +Вольфганг +Вописк +Всеволод +Всеслав +Вук +Вукол +Вышеслав +Вячеслав +Габриеле +Гавриил +Гай +Галактион +Галымжан +Гамлет +Гаспар +Гафур +Гвидо +Гейдар +Геласий +Гелий +Гельмут +Геннадий +Генри +Генрих +Георге +Георгий +Гераклид +Герасим +Герберт +Герман +Германн +Геронтий +Герхард +Гийом +Гильем +Гинкмар +Глеб +Гней +Горацио +Гордей +Градислав +Григорий +Гримоальд +Гуго +Гурий +Густав +Гьялцен +Давид +Дамдинсурэн +Дамир +Даниил +Дарий +Демид +Демьян +Денеш +Денис +Децим +Джаббар +Джамиль +Джан +Джанер +Джанфранко +Джафар +Джейкоб +Джихангир +Джованни +Джон +Джохар +Джулиано +Джулиус +Дино +Диодор +Дитер +Дитмар +Дитрих +Дмитрий +Доминик +Дональд +Донат +Дорофей +Досифей +Евгений +Евграф +Евдоким +Еврит +Евсей +Евстафий +Евтихан +Евтихий +Егор +Елеазар +Елисей +Емельян +Епифаний +Ербол +Ерванд +Еремей +Ермак +Ермолай +Ерофей +Ефим +Ефрем +Жан +Ждан +Жером +Жоан +Захар +Захария +Збигнев +Зденек +Зейналабдин +Зенон +Зеэв +Зигмунд +Зинон +Зия +Золтан +Зосима +Иакинф +Иан +Ибрагим +Ибрахим +Иван +Игнатий +Игорь +Иероним +Иерофей +Израиль +Икрима +Иларий +Илия +Илларион +Илмари +Ильфат +Илья +Имран +Иннокентий +Иоаким +Иоанн +Иоанникий +Иоахим +Иов +Иоганн +Иоганнес +Ионафан +Иосафат +Ираклий +Иржи +Иринарх +Ириней +Иродион +Иса +Исаак +Исаакий +Исаия +Исидор +Ислам +Исмаил +Истислав +Истома +Истукарий +Иштван +Йюрген +Кадваллон +Кадир +Казимир +Каликст +Калин +Каллистрат +Кальман +Канат +Карен +Карлос +Карп +Картерий +Кассиан +Кассий +Касторий +Касьян +Катберт +Квинт +Кехлер +Киллиан +Ким +Кир +Кириак +Кирилл +Клаас +Клавдиан +Клеоник +Климент +Кондрат +Конон +Конрад +Константин +Корнелиус +Корнилий +Коррадо +Косьма +Кратет +Кратипп +Крис +Криспин +Кристиан +Кронид +Кузьма +Куприян +Курбан +Курт +Кутлуг-Буга +Кэлин +Лаврентий +Лавс +Ладислав +Лазарь +Лайл +Лампрехт +Ландульф +Лев +Леви +Ленни +Леонид +Леонтий +Леонхард +Лиам +Линкей +Логгин +Лоренц +Лоренцо +Луи +Луитпольд +Лука +Лукас +Лукий +Лукьян +Луций +Людовик +Макар +Максим +Максимиан +Максимилиан +Малик +Малх +Мамбет +Маний +Мануил +Мануэль +Мариан +Мариус +Марк +Маркел +Мартын +Марчелло +Матвей +Матео +Матиас +Матфей +Матфий +Махмуд +Меир +Мелентий +Мелитон +Менахем-Мендель +Месроп +Мефодий +Мечислав +Мика +Микеланджело +Микулаш +Милорад +Мина +Мирко +Мирон +Мирослав +Митрофан +Михаил +Михей +Младан +Модест +Моисей +Мордехай +Мстислав +Мурад +Мухаммед +Мэдисон +Мэлор +Мэлс +Назар +Наиль +Насиф +Натан +Натаниэль +Наум +Нафанаил +Нацагдорж +Нестор +Никандр +Никанор +Никита +Никифор +Никодим +Николай +Нил +Нильс +Ноа +Ной +Норд +Нуржан +Нурлан +Овадья +Оге +Одинец +Октав +Октавиан +Октавий +Октавио +Олаф +Оле +Олег +Оливер +Ольгерд +Онисим +Орест +Осип +Оскар +Осман +Отто +Оттон +Очирбат +Пабло +Павел +Павлин +Павсикакий +Паисий +Палладий +Панкратий +Пантелеймон +Паруйр +Парфений +Патрик +Пафнутий +Пахомий +Педро +Пётр +Пимен +Пинхас +Пипин +Питирим +Пол +Полидор +Полиевкт +Поликарп +Поликрат +Порфирий +Потап +Предраг +Премысл +Приск +Прокл +Прокопий +Прокул +Протасий +Прохор +Публий +Рагнар +Рагуил +Радмир +Радослав +Разумник +Раймонд +Рамадан +Рамазан +Рахман +Рашад +Рейнхард +Ренат +Реститут +Ричард +Роберт +Родерик +Родион +Рожер +Розарио +Роман +Ромен +Рон +Ронан +Ростислав +Рудольф +Руслан +Руф +Руфин +Рушан +Сабит +Савва +Савватий +Савелий +Савин +Саддам +Садик +Саид +Салават +Салих +Саллюстий +Салман +Самуил +Сармат +Святослав +Севастьян +Северин +Секст +Секунд +Семён +Септимий +Серапион +Сергей +Серж +Сигеберт +Сильвестр +Симеон +Симон +Созон +Соломон +Сонам +Софрон +Спиридон +Срджан +Станислав +Степан +Стефано +Стивен +Таврион +Тавус +Тадеуш +Тарас +Тарасий +Тейс +Тендзин +Теофил +Терентий +Терри +Тиберий +Тигран +Тимофей +Тимур +Тихомир +Тихон +Томас +Томоми +Торос +Тофик +Трифон +Трофим +Тудхалия +Тутмос +Тьерри +Тьяго +Уве +Уильям +Улдис +Ульрих +Ульф +Умар +Урызмаг +Усама +Усман +Фавст +Фаддей +Файзулла +Фарид +Фахраддин +Федериго +Фёдор +Федосей +Федот +Фейсал +Феликс +Феоктист +Феофан +Феофил +Феофилакт +Фердинанд +Ференц +Фидель +Филарет +Филат +Филип +Филипп +Философ +Филострат +Фирс +Фока +Фома +Фотий +Франц +Франческо +Фредерик +Фридрих +Фрол +Фульк +Хайме +Ханс +Харальд +Харитон +Харри +Харрисон +Хасан +Хетаг +Хильдерик +Хирам +Хлодвиг +Хокон +Хорив +Хоселито +Хосрой +Хрисанф +Христофор +Хуан +Цэрэндорж +Чеслав +Шалом +Шамиль +Шамсуддин +Шапур +Шарль +Шейх-Хайдар +Шон +Эберхард +Эдмунд +Эдуард +Элбэгдорж +Элджернон +Элиас +Эллиот +Эмиль +Энрик +Энрико +Энтони +Эразм +Эраст +Эрик +Эрнст +Эсекьель +Эстебан +Этьен +Ювеналий +Юлиан +Юлий +Юлиус +Юрий +Юстас +Юстин +Яков +Якуб +Якун +Ян +Яни +Януарий +Яромир +Ярополк +Ярослав +Барни +Бендер +Бэтмен +Винни +Волдеморт +Гарри +Гэндальф +Дамблдор +Дарт +Декард +Джесси +Кратос +Карлсон +Лебовски +Локи +Луиджи +Люцифер +Марио +Нео +Папа +Пикачу +Снейп +Соник +Терминатор +Тор +Уолтер +Фродо +Чебурашка +Шерлок +Шрек +Йода diff --git a/client/internal/namegen/data/last_names.txt b/client/internal/namegen/data/last_names.txt new file mode 100644 index 0000000..8b7a0d0 --- /dev/null +++ b/client/internal/namegen/data/last_names.txt @@ -0,0 +1,286 @@ +Абрамов +Авдеев +Агафонов +Аксёнов +Александров +Алексеев +Андреев +Анисимов +Анохин +Антипов +Антонов +Арсеньев +Архипов +Афанасьев +Бабушкин +Балашов +Баранов +Барсуков +Белов +Белый +Бельский +Беляев +Бирюков +Блохин +Богданов +Бойко +Большаков +Бондарев +Борисов +Бородин +Бочаров +Брагин +Буров +Быков +Валуев +Варламов +Васильев +Вдовин +Великий +Викторов +Виноградов +Винокуров +Власов +Волков +Воробьёв +Воронин +Воронов +Воронцов +Гаврилов +Галкин +Герасимов +Глебов +Глухов +Голиков +Голубев +Гончаров +Горбунов +Горелов +Горшков +Григорьев +Гришин +Громов +Гурьев +Гусев +Давыдов +Демидов +Денисов +Дмитриев +Дорофеев +Дроздов +Дубинин +Дьяков +Евдокимов +Егоров +Емельянов +Ермаков +Ермилов +Ерофеев +Ефимов +Ефремов +Жданов +Жилин +Жуков +Журавлёв +Зайцев +Захаров +Зимин +Зиновьев +Золотарёв +Зорин +Зуев +Иванов +Ивлев +Игнатов +Игнатьев +Ильин +Исаев +Истомин +Кабанов +Казаков +Калашников +Калинин +Капустин +Карпов +Касаткин +Киреев +Киселёв +Климов +Кобзев +Ковалёв +Козлов +Комаров +Кондратьев +Коновалов +Константинов +Копылов +Корнилов +Королёв +Коротков +Костин +Котов +Кочетков +Кошелев +Крамской +Краснов +Крылов +Крючков +Кудрявцев +Кудряшов +Кузнецов +Кузьмин +Куликов +Курочкин +Лавров +Латыпов +Лебедев +Логинов +Лопухин +Лукин +Львов +Любимов +Майоров +Макаров +Максимов +Мамонтов +Мартынов +Маслов +Матвеев +Медведев +Мельников +Меньшов +Мещеряков +Миронов +Митрофанов +Михайлов +Михеев +Молчанов +Морозов +Москвин +Мухин +Назаров +Наумов +Некрасов +Нестеров +Никитин +Никифоров +Николаев +Новиков +Овчинников +Одинцов +Олейников +Орлов +Осипов +Островский +Павлов +Пахомов +Пестов +Петров +Покровский +Поляков +Пономарёв +Попов +Прокофьев +Прохоров +Пугачёв +Пушкин +Раевский +Родионов +Рожков +Романов +Русаков +Рыбаков +Савельев +Савин +Сазонов +Самойлов +Сафонов +Селезнёв +Семёнов +Сергеев +Сидоров +Силин +Сильвестров +Симонов +Смирнов +Соболев +Соколов +Соловьёв +Соломин +Сорокин +Сотников +Степанов +Стрельников +Субботин +Суворов +Сухов +Тарасов +Тимофеев +Титов +Тихомиров +Тихонов +Толстой +Третьяков +Трубецкой +Туманов +Усов +Устинов +Ушаков +Фадеев +Федосеев +Филиппов +Фокин +Фомин +Фролов +Фёдоров +Хохлов +Худяков +Цветков +Чайковский +Чернов +Черный +Шаров +Шашков +Швецов +Шилов +Ширяев +Шишкин +Щербаков +Юдин +Яковлев +Аддамс +Балалайкин +Бонд +Гриффин +Гэтсби +Дамблдор +Дурсль +Картошкин +Кеннеди +Корлеоне +Лебовски +Лонгботтом +Малфой +Огурцов +Пинкман +Помидоров +Поттер +Райан +Самоваров +Самогонов +Симпсон +Скайуокер +Сноу +Снейп +Сопрано +Сосискин +Старк +Сталлоне +Тайсон +Таргариен +Уайт +Уизли +Хлебов +Холмс +Чаплин +Шварценеггер diff --git a/client/internal/namegen/namegen.go b/client/internal/namegen/namegen.go new file mode 100644 index 0000000..b4517db --- /dev/null +++ b/client/internal/namegen/namegen.go @@ -0,0 +1,80 @@ +// Package namegen produces random Russian-style display names for +// client identities. Name pools are embedded from data/*.txt. +package namegen + +import ( + _ "embed" + "math/rand/v2" + "strings" +) + +//go:embed data/first_names_male.txt +var rawMaleFirstNames string + +//go:embed data/first_names_female.txt +var rawFemaleFirstNames string + +//go:embed data/last_names.txt +var rawLastNames string + +var ( + maleFirstNames = parseLines(rawMaleFirstNames) + femaleFirstNames = parseLines(rawFemaleFirstNames) + lastNames = parseLines(rawLastNames) +) + +func parseLines(s string) []string { + lines := strings.Split(s, "\n") + out := make([]string, 0, len(lines)) + for _, l := range lines { + l = strings.TrimSpace(l) + if l != "" { + out = append(out, l) + } + } + return out +} + +// feminizeSurname converts a Russian male surname to its female form. +// Operates on runes since Cyrillic letters are multibyte in UTF-8. +// Surnames whose suffixes do not match Russian patterns are returned +// unchanged (covers foreign / meme surnames). +func feminizeSurname(surname string) string { + rs := []rune(surname) + n := len(rs) + if n < 2 { + return surname + } + switch string(rs[n-2:]) { + case "ий", "ый", "ой": + return string(rs[:n-2]) + "ая" + case "ов", "ев", "ёв", "ин", "ын": + return surname + "а" + } + return surname +} + +// SurnameProbability is the chance that Generate returns a name with a surname. +const SurnameProbability = 0.7 + +// Generate returns a random "FirstName" or "FirstName LastName". +// Gender is chosen uniformly; surnames are feminized for female names. +func Generate() string { + isFemale := rand.IntN(2) == 0 + + pool := maleFirstNames + if isFemale { + pool = femaleFirstNames + } + fn := pool[rand.IntN(len(pool))] + + if rand.Float64() >= SurnameProbability { + return fn + } + + ln := lastNames[rand.IntN(len(lastNames))] + if isFemale { + ln = feminizeSurname(ln) + } + return fn + " " + ln +} diff --git a/client/internal/namegen/namegen_test.go b/client/internal/namegen/namegen_test.go new file mode 100644 index 0000000..688da38 --- /dev/null +++ b/client/internal/namegen/namegen_test.go @@ -0,0 +1,162 @@ +package namegen + +import ( + "strings" + "testing" + "unicode/utf8" +) + +func TestParseLinesStripsBlanksAndWhitespace(t *testing.T) { + in := " Иван \n\nПётр\n\t\nСидор\n" + got := parseLines(in) + want := []string{"Иван", "Пётр", "Сидор"} + if len(got) != len(want) { + t.Fatalf("got %v, want %v", got, want) + } + for i := range want { + if got[i] != want[i] { + t.Errorf("idx %d: got %q, want %q", i, got[i], want[i]) + } + } +} + +func TestFeminizeSurname(t *testing.T) { + cases := map[string]string{ + // -ов / -ев / -ёв / -ин / -ын -> +а + "Иванов": "Иванова", + "Лебедев": "Лебедева", + "Соловьёв": "Соловьёва", + "Никитин": "Никитина", + "Солженицын": "Солженицына", + // -ий / -ый / -ой -> -ая + "Чайковский": "Чайковская", + "Белый": "Белая", + "Толстой": "Толстая", + "Великий": "Великая", + "Раевский": "Раевская", + // Foreign / meme: unchanged + "Скайуокер": "Скайуокер", + "Поттер": "Поттер", + "Бонд": "Бонд", + "Сноу": "Сноу", + "Корлеоне": "Корлеоне", + // Edge cases + "": "", + "А": "А", + } + for in, want := range cases { + if got := feminizeSurname(in); got != want { + t.Errorf("feminizeSurname(%q) = %q, want %q", in, got, want) + } + } +} + +func TestPoolsLoaded(t *testing.T) { + if len(maleFirstNames) < 100 { + t.Errorf("male pool too small: %d", len(maleFirstNames)) + } + if len(femaleFirstNames) < 50 { + t.Errorf("female pool too small: %d", len(femaleFirstNames)) + } + if len(lastNames) < 100 { + t.Errorf("last names pool too small: %d", len(lastNames)) + } + t.Logf("pools: male=%d female=%d last=%d", len(maleFirstNames), len(femaleFirstNames), len(lastNames)) +} + +func TestPoolsNoBlankNoDuplicates(t *testing.T) { + for _, p := range []struct { + name string + data []string + }{ + {"male", maleFirstNames}, + {"female", femaleFirstNames}, + {"last", lastNames}, + } { + seen := map[string]bool{} + for _, v := range p.data { + if v == "" { + t.Errorf("%s pool: blank entry", p.name) + } + if !utf8.ValidString(v) { + t.Errorf("%s pool: invalid utf8 %q", p.name, v) + } + if seen[v] { + t.Errorf("%s pool: duplicate %q", p.name, v) + } + seen[v] = true + } + } +} + +func TestGenerateProducesPlausibleName(t *testing.T) { + // Build prefix set of valid first names (may contain spaces, e.g. "Абд аль-Узза"). + firstNameSet := map[string]bool{} + for _, n := range maleFirstNames { + firstNameSet[n] = true + } + for _, n := range femaleFirstNames { + firstNameSet[n] = true + } + + withSurname := 0 + const iters = 2000 + for range iters { + n := Generate() + if n == "" { + t.Fatal("Generate returned empty string") + } + // Either the whole string is a first name, or it splits into + // " " at the LAST space. + if firstNameSet[n] { + continue + } + idx := strings.LastIndex(n, " ") + if idx < 0 { + t.Errorf("unrecognized name %q", n) + continue + } + first, last := n[:idx], n[idx+1:] + if !firstNameSet[first] { + t.Errorf("unknown first-name prefix in %q", n) + } + if last == "" { + t.Errorf("empty surname in %q", n) + } + withSurname++ + } + // SurnameProbability = 0.7; allow generous slack to avoid flake. + ratio := float64(withSurname) / float64(iters) + if ratio < 0.6 || ratio > 0.8 { + t.Errorf("surname ratio %.2f out of expected band [0.60, 0.80]", ratio) + } +} + +func TestGenerateCoversBothGenders(t *testing.T) { + maleSet := map[string]bool{} + for _, n := range maleFirstNames { + maleSet[n] = true + } + femaleSet := map[string]bool{} + for _, n := range femaleFirstNames { + femaleSet[n] = true + } + + sawMale, sawFemale := false, false + for i := 0; i < 5000 && !(sawMale && sawFemale); i++ { //nolint:intrange // need early exit + n := Generate() + first := strings.SplitN(n, " ", 2)[0] + if maleSet[first] { + sawMale = true + } + if femaleSet[first] { + sawFemale = true + } + } + if !sawMale { + t.Error("no male names seen in 5000 iterations") + } + if !sawFemale { + t.Error("no female names seen in 5000 iterations") + } +} diff --git a/client/main.go b/client/main.go index c1575d0..1f2b2d6 100644 --- a/client/main.go +++ b/client/main.go @@ -31,6 +31,7 @@ import ( "github.com/cacggghp/vk-turn-proxy/client/internal/browserprofile" "github.com/cacggghp/vk-turn-proxy/client/internal/captcha" "github.com/cacggghp/vk-turn-proxy/client/internal/dnsdial" + "github.com/cacggghp/vk-turn-proxy/client/internal/namegen" "github.com/cacggghp/vk-turn-proxy/tcputil" "github.com/cbeuw/connutil" "github.com/google/uuid" @@ -584,7 +585,7 @@ func getTokenChain(ctx context.Context, link string, streamID int, creds VKCrede return "", "", nil, fmt.Errorf("failed to initialize tls_client: %w", err) } - name := generateName() + name := namegen.Generate() escapedName := neturl.QueryEscape(name) log.Printf("[STREAM %d] [VK Auth] Connecting Identity - Name: %s | User-Agent: %s", streamID, name, profile.UserAgent) diff --git a/client/namegen.go b/client/namegen.go deleted file mode 100644 index 916bc78..0000000 --- a/client/namegen.go +++ /dev/null @@ -1,883 +0,0 @@ -package main - -import ( - "fmt" - "math/rand" - "strings" -) - -var maleFirstNames = []string{ - "Аарон", - "Аба", - "Аббас", - "Абд аль-Узза", - "Абдуллах", - "Абид", - "Аботур", - "Аввакум", - "Август", - "Авдей", - "Авель", - "Аверкий", - "Авигдор", - "Авирмэд", - "Авксентий", - "Авл", - "Авнер", - "Аврелий", - "Автандил", - "Автоном", - "Агапит", - "Агафангел", - "Агафодор", - "Агафон", - "Аги", - "Агриппа", - "Адам", - "Адар", - "Адиль", - "Адольф", - "Адонирам", - "Адриан", - "Азамат", - "Азарий", - "Азат", - "Азиз", - "Азим", - "Айварс", - "Айдар", - "Айрат", - "Акакий", - "Аквилий", - "Акиф", - "Акоп", - "Аксель", - "Алан", - "Аланус", - "Алек", - "Александр", - "Алексей", - "Алемдар", - "Алик", - "Алим", - "Алипий", - "Алишер", - "Алмат", - "Алоиз", - "Алон", - "Альберик", - "Альберт", - "Альбин", - "Альваро", - "Альвиан", - "Альвизе", - "Альфонс", - "Альфред", - "Амадис", - "Амвросий", - "Амедей", - "Амин", - "Амир", - "Амр", - "Амфилохий", - "Анания", - "Анас", - "Анастасий", - "Анатолий", - "Ангеляр", - "Андокид", - "Андрей", - "Андроник", - "Аннерс", - "Анри", - "Ансельм", - "Антипа", - "Антон", - "Антоний", - "Антонин", - "Антуан", - "Арам", - "Арефа", - "Арзуман", - "Аристарх", - "Аристон", - "Ариф", - "Аркадий", - "Арсений", - "Артём", - "Артур", - "Арфаксад", - "Асаф", - "Атанасий", - "Атом", - "Аттик", - "Афанасий", - "Афинагор", - "Афиней", - "Афиф", - "Африкан", - "Ахилл", - "Ахмад", - "Ахтям", - "Ашот", - "Бадар", - "Барни", - "Бартоломео", - "Басир", - "Бахтияр", - "Баян", - "Безсон", - "Бен", - "Беньямин", - "Берт", - "Бехруз", - "Билял", - "Богдан", - "Болеслав", - "Бонавентура", - "Борис", - "Борислав", - "Боян", - "Бронислав", - "Брячислав", - "Бурхан", - "Бутрос", - "Бямбасурэн", - "Вадим", - "Валентин", - "Валентино", - "Валерий", - "Валерьян", - "Вальдемар", - "Вангьял", - "Варлам", - "Варнава", - "Варфоломей", - "Василий", - "Вахтанг", - "Велвел", - "Венансио", - "Венедикт", - "Вениамин", - "Венцеслав", - "Вигго", - "Викентий", - "Виктор", - "Викторин", - "Вильгельм", - "Винцас", - "Виссарион", - "Виталий", - "Витаутас", - "Вито", - "Владимир", - "Владислав", - "Владлен", - "Влас", - "Воислав", - "Володарь", - "Вольфганг", - "Вописк", - "Всеволод", - "Всеслав", - "Вук", - "Вукол", - "Вышеслав", - "Вячеслав", - "Габриеле", - "Гавриил", - "Гай", - "Галактион", - "Галымжан", - "Гамлет", - "Гаспар", - "Гафур", - "Гвидо", - "Гейдар", - "Геласий", - "Гелий", - "Гельмут", - "Геннадий", - "Генри", - "Генрих", - "Георге", - "Георгий", - "Гераклид", - "Герасим", - "Герберт", - "Герман", - "Германн", - "Геронтий", - "Герхард", - "Гийом", - "Гильем", - "Гинкмар", - "Глеб", - "Гней", - "Гоар", - "Горацио", - "Гордей", - "Градислав", - "Григорий", - "Гримоальд", - "Гуго", - "Гурий", - "Густав", - "Гьялцен", - "Давид", - "Дамдинсурэн", - "Дамир", - "Даниил", - "Дарий", - "Демид", - "Демьян", - "Денеш", - "Денис", - "Децим", - "Джаббар", - "Джамиль", - "Джан", - "Джанер", - "Джанфранко", - "Джафар", - "Джейкоб", - "Джихангир", - "Джованни", - "Джон", - "Джохар", - "Джулиано", - "Джулиус", - "Дино", - "Диодор", - "Дитер", - "Дитмар", - "Дитрих", - "Дмитрий", - "Доминик", - "Дональд", - "Донат", - "Дорофей", - "Досифей", - "Евгений", - "Евграф", - "Евдоким", - "Еврит", - "Евсей", - "Евстафий", - "Евтихан", - "Евтихий", - "Егор", - "Елеазар", - "Елисей", - "Емельян", - "Епифаний", - "Ербол", - "Ерванд", - "Еремей", - "Ермак", - "Ермолай", - "Ерофей", - "Ефим", - "Ефрем", - "Жан", - "Ждан", - "Жером", - "Жоан", - "Захар", - "Захария", - "Збигнев", - "Зденек", - "Зейналабдин", - "Зенон", - "Зеэв", - "Зигмунд", - "Зинон", - "Зия", - "Золтан", - "Зосима", - "Иакинф", - "Иан", - "Ибрагим", - "Ибрахим", - "Иван", - "Игнатий", - "Игорь", - "Иероним", - "Иерофей", - "Израиль", - "Икрима", - "Иларий", - "Илия", - "Илларион", - "Илмари", - "Ильфат", - "Илья", - "Имран", - "Иннокентий", - "Иоаким", - "Иоанн", - "Иоанникий", - "Иоахим", - "Иов", - "Иоганн", - "Иоганнес", - "Ионафан", - "Иосафат", - "Ираклий", - "Иржи", - "Иринарх", - "Ириней", - "Иродион", - "Иса", - "Исаак", - "Исаакий", - "Исаия", - "Исидор", - "Ислам", - "Исмаил", - "Истислав", - "Истома", - "Истукарий", - "Иштван", - "Йюрген", - "Кадваллон", - "Кадир", - "Казимир", - "Каликст", - "Калин", - "Каллистрат", - "Кальман", - "Канат", - "Карен", - "Карлос", - "Карп", - "Картерий", - "Кассиан", - "Кассий", - "Касторий", - "Касьян", - "Катберт", - "Квинт", - "Кехлер", - "Киллиан", - "Ким", - "Кир", - "Кириак", - "Кирилл", - "Клаас", - "Клавдиан", - "Клеоник", - "Климент", - "Кондрат", - "Конон", - "Конрад", - "Константин", - "Корнелиус", - "Корнилий", - "Коррадо", - "Косьма", - "Кратет", - "Кратипп", - "Крис", - "Криспин", - "Кристиан", - "Кронид", - "Кузьма", - "Куприян", - "Курбан", - "Курт", - "Кутлуг-Буга", - "Кэлин", - "Лаврентий", - "Лавс", - "Ладислав", - "Лазарь", - "Лайл", - "Лампрехт", - "Ландульф", - "Лев", - "Леви", - "Ленни", - "Леонид", - "Леонтий", - "Леонхард", - "Лиам", - "Линкей", - "Логгин", - "Лоренц", - "Лоренцо", - "Луи", - "Луитпольд", - "Лука", - "Лукас", - "Лукий", - "Лукьян", - "Луций", - "Людовик", - "Люцифер", - "Макар", - "Максим", - "Максимиан", - "Максимилиан", - "Малик", - "Малх", - "Мамбет", - "Маний", - "Мануил", - "Мануэль", - "Мариан", - "Мариус", - "Марк", - "Маркел", - "Мартын", - "Марчелло", - "Матвей", - "Матео", - "Матиас", - "Матфей", - "Матфий", - "Махмуд", - "Меир", - "Мелентий", - "Мелитон", - "Менахем-Мендель", - "Месроп", - "Мефодий", - "Мечислав", - "Мика", - "Микеланджело", - "Микулаш", - "Милорад", - "Мина", - "Мирко", - "Мирон", - "Мирослав", - "Митрофан", - "Михаил", - "Михей", - "Младан", - "Модест", - "Моисей", - "Мордехай", - "Мстислав", - "Мурад", - "Мухаммед", - "Мэдисон", - "Мэлор", - "Мэлс", - "Назар", - "Наиль", - "Насиф", - "Натан", - "Натаниэль", - "Наум", - "Нафанаил", - "Нацагдорж", - "Нестор", - "Никандр", - "Никанор", - "Никита", - "Никифор", - "Никодим", - "Николай", - "Нил", - "Нильс", - "Ноа", - "Ной", - "Норд", - "Нуржан", - "Нурлан", - "Овадья", - "Оге", - "Одинец", - "Октав", - "Октавиан", - "Октавий", - "Октавио", - "Олаф", - "Оле", - "Олег", - "Оливер", - "Ольгерд", - "Онисим", - "Орест", - "Осип", - "Оскар", - "Осман", - "Отто", - "Оттон", - "Очирбат", - "Пабло", - "Павел", - "Павлин", - "Павсикакий", - "Паисий", - "Палладий", - "Панкратий", - "Пантелеймон", - "Папа", - "Паруйр", - "Парфений", - "Патрик", - "Пафнутий", - "Пахомий", - "Педро", - "Пётр", - "Пимен", - "Пинхас", - "Пипин", - "Питирим", - "Пол", - "Полидор", - "Полиевкт", - "Поликарп", - "Поликрат", - "Порфирий", - "Потап", - "Предраг", - "Премысл", - "Приск", - "Прокл", - "Прокопий", - "Прокул", - "Протасий", - "Прохор", - "Публий", - "Рагнар", - "Рагуил", - "Радмир", - "Радослав", - "Разумник", - "Раймонд", - "Рамадан", - "Рамазан", - "Рахман", - "Рашад", - "Рейнхард", - "Ренат", - "Реститут", - "Ричард", - "Роберт", - "Родерик", - "Родион", - "Рожер", - "Розарио", - "Роман", - "Ромен", - "Рон", - "Ронан", - "Ростислав", - "Рудольф", - "Руслан", - "Руф", - "Руфин", - "Рушан", - "Сабит", - "Савва", - "Савватий", - "Савелий", - "Савин", - "Саддам", - "Садик", - "Саид", - "Салават", - "Салих", - "Саллюстий", - "Салман", - "Самуил", - "Сармат", - "Святослав", - "Севастьян", - "Северин", - "Секст", - "Секунд", - "Семён", - "Септимий", - "Серапион", - "Сергей", - "Серж", - "Сигеберт", - "Сильвестр", - "Симеон", - "Симон", - "Созон", - "Соломон", - "Сонам", - "Софрон", - "Спиридон", - "Срджан", - "Станислав", - "Степан", - "Стефано", - "Стивен", - "Таврион", - "Тавус", - "Тадеуш", - "Тарас", - "Тарасий", - "Тейс", - "Тендзин", - "Теофил", - "Терентий", - "Терри", - "Тиберий", - "Тигран", - "Тимофей", - "Тимур", - "Тихомир", - "Тихон", - "Томас", - "Томоми", - "Торос", - "Тофик", - "Трифон", - "Трофим", - "Тудхалия", - "Тутмос", - "Тьерри", - "Тьяго", - "Уве", - "Уильям", - "Улдис", - "Ульрих", - "Ульф", - "Умар", - "Урызмаг", - "Усама", - "Усман", - "Фавст", - "Фаддей", - "Файзулла", - "Фарид", - "Фахраддин", - "Федериго", - "Фёдор", - "Федосей", - "Федот", - "Фейсал", - "Феликс", - "Феоктист", - "Феофан", - "Феофил", - "Феофилакт", - "Фердинанд", - "Ференц", - "Фидель", - "Филарет", - "Филат", - "Филип", - "Филипп", - "Философ", - "Филострат", - "Фирс", - "Фока", - "Фома", - "Фотий", - "Франц", - "Франческо", - "Фредерик", - "Фридрих", - "Фродо", - "Фрол", - "Фульк", - "Хайме", - "Ханс", - "Харальд", - "Харитон", - "Харри", - "Харрисон", - "Хасан", - "Хетаг", - "Хильдерик", - "Хирам", - "Хлодвиг", - "Хокон", - "Хорив", - "Хоселито", - "Хосрой", - "Хрисанф", - "Христофор", - "Хуан", - "Цэрэндорж", - "Чеслав", - "Шалом", - "Шамиль", - "Шамсуддин", - "Шапур", - "Шарль", - "Шейх-Хайдар", - "Шон", - "Эберхард", - "Эдмунд", - "Эдна", - "Эдуард", - "Элбэгдорж", - "Элджернон", - "Элиас", - "Эллиот", - "Эмиль", - "Энрик", - "Энрико", - "Энтони", - "Эразм", - "Эраст", - "Эрик", - "Эрнст", - "Эсекьель", - "Эстебан", - "Этьен", - "Ювеналий", - "Юлиан", - "Юлий", - "Юлиус", - "Юрий", - "Юстас", - "Юстин", - "Яков", - "Якуб", - "Якун", - "Ян", - "Яни", - "Януарий", - "Яромир", - "Ярополк", - "Ярослав", -} - -var femaleFirstNames = []string{ - "Алина", - "Алёна", - "Анастасия", - "Ангелина", - "Анна", - "Вера", - "Вероника", - "Виктория", - "Дарья", - "Ева", - "Екатерина", - "Елена", - "Елизавета", - "Ирина", - "Кира", - "Кристина", - "Ксения", - "Любовь", - "Маргарита", - "Марина", - "Мария", - "Милана", - "Надежда", - "Наталья", - "Ольга", - "Полина", - "Светлана", - "София", - "Татьяна", - "Юлия", - "Яна", -} - -var lastNames = []string{ - "Алексеев", - "Андреев", - "Антонов", - "Баранов", - "Белов", - "Белый", - "Бельский", - "Беляев", - "Борисов", - "Васильев", - "Великий", - "Волков", - "Воробьёв", - "Григорьев", - "Давыдов", - "Егоров", - "Жуков", - "Зайцев", - "Захаров", - "Иванов", - "Калинин", - "Ковалёв", - "Козлов", - "Комаров", - "Крамской", - "Кузнецов", - "Кузьмин", - "Лебедев", - "Макаров", - "Медведев", - "Михайлов", - "Морозов", - "Никитин", - "Николаев", - "Новиков", - "Орлов", - "Островский", - "Павлов", - "Петров", - "Покровский", - "Попов", - "Раевский", - "Романов", - "Семёнов", - "Сергеев", - "Смирнов", - "Соколов", - "Соловьёв", - "Степанов", - "Тарасов", - "Титов", - "Толстой", - "Трубецкой", - "Филиппов", - "Фролов", - "Фёдоров", - "Чайковский", - "Черный", - "Яковлев", -} - -// convertToFemaleSurname handles Russian suffix rules -func convertToFemaleSurname(surname string) string { - // Handle adjective-style surnames: - if strings.HasSuffix(surname, "ий") || strings.HasSuffix(surname, "ый") || strings.HasSuffix(surname, "ой") { - return surname[:len(surname)-4] + "ая" - } - - // Handle standard possessive surnames: - if strings.HasSuffix(surname, "ов") || strings.HasSuffix(surname, "ев") || - strings.HasSuffix(surname, "ин") || strings.HasSuffix(surname, "ын") || - strings.HasSuffix(surname, "ёв") { - return surname + "а" - } - - // Foreign or unchangeable - return surname -} - -func generateName() string { - // Decide gender first - isFemale := rand.Intn(2) == 0 - - var fn string - if isFemale { - fn = femaleFirstNames[rand.Intn(len(femaleFirstNames))] - } else { - fn = maleFirstNames[rand.Intn(len(maleFirstNames))] - } - - // 70% chance to have a last name - if rand.Float32() < 0.3 { - return fn - } - - ln := lastNames[rand.Intn(len(lastNames))] - if isFemale { - ln = convertToFemaleSurname(ln) - } - - return fmt.Sprintf("%s %s", fn, ln) -}