status_length_validator.rb 786 B

123456789101112131415161718192021222324252627282930313233343536
  1. # frozen_string_literal: true
  2. class StatusLengthValidator < ActiveModel::Validator
  3. MAX_CHARS = 500
  4. URL_PLACEHOLDER = "\1#{'x' * 23}"
  5. def validate(status)
  6. return unless status.local? && !status.reblog?
  7. @status = status
  8. status.errors.add(:text, I18n.t('statuses.over_character_limit', max: MAX_CHARS)) if too_long?
  9. end
  10. private
  11. def too_long?
  12. countable_length > MAX_CHARS
  13. end
  14. def countable_length
  15. total_text.mb_chars.grapheme_length
  16. end
  17. def total_text
  18. [@status.spoiler_text, countable_text].join
  19. end
  20. def countable_text
  21. return '' if @status.text.nil?
  22. @status.text.dup.tap do |new_text|
  23. new_text.gsub!(FetchLinkCardService::URL_PATTERN, URL_PLACEHOLDER)
  24. new_text.gsub!(Account::MENTION_RE, '@\2')
  25. end
  26. end
  27. end