151 lines
4.0 KiB
JavaScript
151 lines
4.0 KiB
JavaScript
const BLOCK_TIERS = [
|
|
{ threshold: 15, durationMs: null, permanent: true },
|
|
{ threshold: 10, durationMs: 30 * 24 * 60 * 60 * 1000 },
|
|
{ threshold: 5, durationMs: 7 * 24 * 60 * 60 * 1000 },
|
|
{ threshold: 3, durationMs: 24 * 60 * 60 * 1000 },
|
|
]
|
|
|
|
const formatRemainingPersian = (blockedUntil) => {
|
|
if (!blockedUntil) return ''
|
|
const diffMs = new Date(blockedUntil).getTime() - Date.now()
|
|
if (diffMs <= 0) return ''
|
|
|
|
const totalMinutes = Math.ceil(diffMs / (60 * 1000))
|
|
const days = Math.floor(totalMinutes / (24 * 60))
|
|
const hours = Math.floor((totalMinutes % (24 * 60)) / 60)
|
|
const minutes = totalMinutes % 60
|
|
|
|
const parts = []
|
|
if (days > 0) parts.push(`${days} روز`)
|
|
if (hours > 0) parts.push(`${hours} ساعت`)
|
|
if (minutes > 0 || parts.length === 0) parts.push(`${minutes} دقیقه`)
|
|
|
|
return parts.join(' و ')
|
|
}
|
|
|
|
const getBlockTier = (blockCount) => {
|
|
return BLOCK_TIERS.find((tier) => blockCount >= tier.threshold) || null
|
|
}
|
|
|
|
const applyAutoBlockSuspension = (user) => {
|
|
const blockCount = user.blocked_by?.length || 0
|
|
const tier = getBlockTier(blockCount)
|
|
|
|
if (!tier) {
|
|
if (user.block_permanent && user.account_status === 'deactivated') {
|
|
user.account_status = 'active'
|
|
}
|
|
user.block_status = null
|
|
user.blocked_until = null
|
|
user.block_permanent = false
|
|
return
|
|
}
|
|
|
|
user.block_status = true
|
|
|
|
if (tier.permanent) {
|
|
user.block_permanent = true
|
|
user.blocked_until = null
|
|
user.account_status = 'deactivated'
|
|
return
|
|
}
|
|
|
|
user.block_permanent = false
|
|
|
|
const currentUntil = user.blocked_until ? new Date(user.blocked_until).getTime() : 0
|
|
const newUntil = Date.now() + tier.durationMs
|
|
if (!user.blocked_until || newUntil > currentUntil) {
|
|
user.blocked_until = new Date(newUntil)
|
|
}
|
|
}
|
|
|
|
const clearAutoBlockSuspension = (user) => {
|
|
applyAutoBlockSuspension(user)
|
|
}
|
|
|
|
const isUserCurrentlyBlocked = (user) => {
|
|
if (!user?.block_status) {
|
|
return false
|
|
}
|
|
|
|
if (user.block_permanent) {
|
|
return true
|
|
}
|
|
|
|
if (user.blocked_until) {
|
|
if (new Date() >= new Date(user.blocked_until)) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
return user.block_status === true
|
|
}
|
|
|
|
const expireBlockSuspensionIfNeeded = async (user) => {
|
|
if (user.block_permanent) {
|
|
return user
|
|
}
|
|
|
|
if (!user.blocked_until) {
|
|
return user
|
|
}
|
|
|
|
if (new Date() >= new Date(user.blocked_until)) {
|
|
const blockCount = user.blocked_by?.length || 0
|
|
applyAutoBlockSuspension(user)
|
|
if (!isUserCurrentlyBlocked(user)) {
|
|
user.block_status = null
|
|
user.blocked_until = null
|
|
}
|
|
try {
|
|
await user.save({ validateModifiedOnly: true })
|
|
} catch (saveError) {
|
|
console.error('[expireBlockSuspensionIfNeeded] save failed:', saveError)
|
|
}
|
|
}
|
|
|
|
return user
|
|
}
|
|
|
|
const getBlockedAccountResponse = (user) => {
|
|
if (!isUserCurrentlyBlocked(user)) {
|
|
return null
|
|
}
|
|
|
|
if (user.block_permanent || (user.blocked_by?.length || 0) >= 15) {
|
|
return {
|
|
status: 'error',
|
|
code: 403,
|
|
message:
|
|
'کاربر گرامی اکانت شما به علت تخلف زیاد و گزارش توسط کاربران دیگر غیر فعال می باشد.',
|
|
type: 'block',
|
|
blocked_until: null,
|
|
permanent: true,
|
|
}
|
|
}
|
|
|
|
const remaining = formatRemainingPersian(user.blocked_until)
|
|
|
|
return {
|
|
status: 'error',
|
|
code: 403,
|
|
message: remaining
|
|
? `به مدت ${remaining} از انجام هر گونه عملیات در سایت مسدود هستید.`
|
|
: 'حساب کاربری شما موقتاً مسدود شده است.',
|
|
type: 'block',
|
|
blocked_until: user.blocked_until || null,
|
|
permanent: false,
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
BLOCK_TIERS,
|
|
applyAutoBlockSuspension,
|
|
clearAutoBlockSuspension,
|
|
isUserCurrentlyBlocked,
|
|
expireBlockSuspensionIfNeeded,
|
|
getBlockedAccountResponse,
|
|
formatRemainingPersian,
|
|
}
|