The old limit was one appeal per day. The new limit is based on your upload limit. Each appeal costs 3 upload slots. If you have 15 upload slots, then you can appeal up to 5 posts at once, but you won't be able to appeal or upload more until your appeals are approved or rejected. If you have unlimited uploads, then you have unlimited appeals.
121 lines
2.6 KiB
Ruby
121 lines
2.6 KiB
Ruby
class UploadLimit
|
|
extend Memoist
|
|
|
|
INITIAL_POINTS = 1000
|
|
MAXIMUM_POINTS = 10_000
|
|
APPEAL_COST = 3
|
|
|
|
attr_reader :user
|
|
|
|
def initialize(user)
|
|
@user = user
|
|
end
|
|
|
|
def limited?
|
|
if user.can_upload_free?
|
|
false
|
|
elsif user.created_at > 1.week.ago
|
|
true
|
|
else
|
|
used_upload_slots >= upload_slots
|
|
end
|
|
end
|
|
|
|
def limit_reason
|
|
if user.created_at > 1.week.ago
|
|
"cannot upload during your first week of registration"
|
|
elsif limited?
|
|
"have reached your upload limit"
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
def used_upload_slots
|
|
pending_count = user.posts.pending.count
|
|
appealed_count = user.post_appeals.pending.count
|
|
early_deleted_count = user.posts.deleted.where("created_at >= ?", 3.days.ago).count
|
|
|
|
pending_count + early_deleted_count + (appealed_count * APPEAL_COST)
|
|
end
|
|
|
|
def free_upload_slots
|
|
upload_slots - used_upload_slots
|
|
end
|
|
|
|
def upload_slots
|
|
upload_level + 5
|
|
end
|
|
|
|
def upload_level
|
|
UploadLimit.points_to_level(user.upload_points)
|
|
end
|
|
|
|
def approvals_on_current_level
|
|
(user.upload_points - UploadLimit.level_to_points(upload_level)) / 10
|
|
end
|
|
|
|
def approvals_for_next_level
|
|
UploadLimit.points_for_next_level(upload_level) / 10
|
|
end
|
|
|
|
def update_limit!(post, incremental: true)
|
|
return if user.can_upload_free?
|
|
|
|
user.with_lock do
|
|
if incremental
|
|
user.upload_points += UploadLimit.upload_value(user.upload_points, post.is_deleted)
|
|
user.upload_points = user.upload_points.clamp(0, MAXIMUM_POINTS)
|
|
user.save!
|
|
else
|
|
user.update!(upload_points: UploadLimit.points_for_user(user))
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.points_for_user(user)
|
|
points = INITIAL_POINTS
|
|
|
|
uploads = user.posts.where(is_pending: false).order(id: :asc).pluck(:is_deleted)
|
|
uploads.each do |is_deleted|
|
|
points += upload_value(points, is_deleted)
|
|
points = points.clamp(0, MAXIMUM_POINTS)
|
|
|
|
# warn "slots: %2d, points: %3d, value: %2d" % [UploadLimit.points_to_level(points) + 5, points, UploadLimit.upload_value(level, is_deleted)]
|
|
end
|
|
|
|
points
|
|
end
|
|
|
|
def self.upload_value(current_points, is_deleted)
|
|
if is_deleted
|
|
level = points_to_level(current_points)
|
|
-1 * (points_for_next_level(level) / 3.0).round.to_i
|
|
else
|
|
10
|
|
end
|
|
end
|
|
|
|
def self.points_for_next_level(level)
|
|
100 + 20 * [level - 10, 0].max
|
|
end
|
|
|
|
def self.points_to_level(points)
|
|
level = 0
|
|
|
|
loop do
|
|
points -= points_for_next_level(level)
|
|
break if points < 0
|
|
level += 1
|
|
end
|
|
|
|
level
|
|
end
|
|
|
|
def self.level_to_points(level)
|
|
(1..level).map do |n|
|
|
points_for_next_level(n - 1)
|
|
end.sum
|
|
end
|
|
end
|