Initial commit

This commit is contained in:
payacom
2026-07-07 12:49:09 +03:30
parent 5719818b9d
commit a7e4f68495
3 changed files with 150 additions and 15 deletions

View File

@@ -0,0 +1,69 @@
const { validateUsername, USERNAME_MAX_LENGTH } = require('./usernameValidation')
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
const isUsernameTaken = async (UserModel, userName, excludeUserId) => {
const existing = await UserModel.findOne({
user_name: { $regex: new RegExp(`^${escapeRegex(userName)}$`, 'i') }
})
if (!existing) return false
if (excludeUserId && existing._id.toString() === excludeUserId) return false
return true
}
const buildCandidates = (base, attempt) => {
const random2 = () => String(Math.floor(Math.random() * 90 + 10))
const random3 = () => String(Math.floor(Math.random() * 900 + 100))
const random4 = () => String(Math.floor(Math.random() * 9000 + 1000))
const builders = [
(b) => `${b}${random2()}`,
(b) => `${b}_${random3()}`,
(b) => `${b}.${random2()}`,
(b) => `${b}-${random2()}`,
(b) => `${b}${random4()}`,
(b) => `${b}_m${random2()}`,
(b) => `${b}${attempt}`,
]
return builders.map((fn) => {
let candidate = fn(base)
if (candidate.length > USERNAME_MAX_LENGTH) {
candidate = candidate.slice(0, USERNAME_MAX_LENGTH)
}
return candidate
})
}
const generateUsernameSuggestions = async (
UserModel,
baseUsername,
excludeUserId,
count = 3
) => {
const base = baseUsername.trim().toLowerCase()
const suggestions = []
const tried = new Set([base])
for (let attempt = 1; attempt <= 60 && suggestions.length < count; attempt++) {
const candidates = buildCandidates(base, attempt)
for (const candidate of candidates) {
if (suggestions.length >= count) break
if (tried.has(candidate)) continue
tried.add(candidate)
if (validateUsername(candidate)) continue
const taken = await isUsernameTaken(UserModel, candidate, excludeUserId)
if (!taken) suggestions.push(candidate)
}
}
return suggestions
}
module.exports = {
generateUsernameSuggestions,
isUsernameTaken
}

View File

@@ -0,0 +1,33 @@
/** حروف انگلیسی، اعداد و . _ - — بدون فارسی و کاراکترهای غیرمعمول */
const USERNAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9._-]{5,99}$/
const USERNAME_MIN_LENGTH = 6
const USERNAME_MAX_LENGTH = 100
const validateUsername = (user_name) => {
if (!user_name || typeof user_name !== 'string') {
return 'نام کاربری الزامی است'
}
const trimmed = user_name.trim()
if (trimmed.length < USERNAME_MIN_LENGTH) {
return `نام کاربری باید حداقل ${USERNAME_MIN_LENGTH} کاراکتر باشد`
}
if (trimmed.length > USERNAME_MAX_LENGTH) {
return `نام کاربری نمی‌تواند بیشتر از ${USERNAME_MAX_LENGTH} کاراکتر باشد`
}
if (!USERNAME_REGEX.test(trimmed)) {
return 'نام کاربری فقط می‌تواند شامل حروف انگلیسی، اعداد و کاراکترهای . _ - باشد'
}
return null
}
module.exports = {
USERNAME_REGEX,
USERNAME_MIN_LENGTH,
USERNAME_MAX_LENGTH,
validateUsername
}