2024-02-25 12:15:55 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-06-14 22:27:53 -04:00
|
|
|
class Dmail < ApplicationRecord
|
2024-11-10 23:22:40 -05:00
|
|
|
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
|
2019-09-05 08:59:51 -04:00
|
|
|
validates :title, :body, presence: { on: :create }
|
|
|
|
validates :title, length: { minimum: 1, maximum: 250 }
|
2021-10-31 23:30:37 -04:00
|
|
|
validates :body, length: { minimum: 1, maximum: Danbooru.config.dmail_max_size }
|
2019-10-03 10:29:49 -04:00
|
|
|
validate :recipient_accepts_dmails, on: :create
|
2019-06-27 11:33:02 -04:00
|
|
|
validate :user_not_limited, on: :create
|
2017-02-23 16:46:12 -05:00
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
belongs_to :owner, :class_name => "User"
|
|
|
|
belongs_to :to, :class_name => "User"
|
|
|
|
belongs_to :from, :class_name => "User"
|
2017-02-23 21:01:32 -05:00
|
|
|
|
|
|
|
after_initialize :initialize_attributes, if: :new_record?
|
2015-08-13 20:16:24 -04:00
|
|
|
before_create :auto_read_if_filtered
|
2010-02-20 18:08:22 -05:00
|
|
|
after_create :update_recipient
|
2023-06-02 10:04:49 -04:00
|
|
|
after_commit :send_email, on: :create, unless: :no_email_notification
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2023-06-02 10:04:49 -04:00
|
|
|
attr_accessor :bypass_limits, :no_email_notification
|
2020-03-12 22:36:08 -04:00
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
module AddressMethods
|
|
|
|
def to_name=(name)
|
2017-02-23 21:03:09 -05:00
|
|
|
self.to_id = User.name_to_id(name)
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2017-02-23 21:01:32 -05:00
|
|
|
def initialize_attributes
|
|
|
|
self.from_id ||= CurrentUser.id
|
|
|
|
self.creator_ip_addr ||= CurrentUser.ip_addr
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
module FactoryMethods
|
2010-11-19 16:24:17 -05:00
|
|
|
extend ActiveSupport::Concern
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
module ClassMethods
|
2010-11-19 16:24:17 -05:00
|
|
|
def create_split(params)
|
2010-12-05 22:27:45 -05:00
|
|
|
copy = nil
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2010-11-19 16:24:17 -05:00
|
|
|
Dmail.transaction do
|
2017-02-23 21:15:29 -05:00
|
|
|
# recipient's copy
|
2010-11-19 16:24:17 -05:00
|
|
|
copy = Dmail.new(params)
|
|
|
|
copy.owner_id = copy.to_id
|
2017-02-23 21:15:29 -05:00
|
|
|
copy.save unless copy.to_id == copy.from_id
|
2023-09-17 10:40:33 -04:00
|
|
|
raise ActiveRecord::Rollback if copy.errors.any?
|
2010-02-20 18:08:22 -05:00
|
|
|
|
2017-02-23 21:15:29 -05:00
|
|
|
# sender's copy
|
2010-11-19 16:24:17 -05:00
|
|
|
copy = Dmail.new(params)
|
2021-06-19 13:20:30 -04:00
|
|
|
copy.bypass_limits = true
|
2017-02-23 21:15:29 -05:00
|
|
|
copy.owner_id = copy.from_id
|
2012-02-24 17:39:55 -05:00
|
|
|
copy.is_read = true
|
2012-01-20 17:19:08 -05:00
|
|
|
copy.save
|
2010-11-19 16:24:17 -05:00
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2010-12-05 22:27:45 -05:00
|
|
|
copy
|
2010-11-19 16:24:17 -05:00
|
|
|
end
|
2017-02-23 21:15:29 -05:00
|
|
|
|
|
|
|
def create_automated(params)
|
2018-04-27 17:44:43 -04:00
|
|
|
CurrentUser.as_system do
|
|
|
|
dmail = Dmail.new(from: User.system, **params)
|
|
|
|
dmail.owner = dmail.to
|
|
|
|
dmail.save
|
2018-04-27 18:04:27 -04:00
|
|
|
dmail
|
2018-04-27 17:44:43 -04:00
|
|
|
end
|
2017-02-23 21:15:29 -05:00
|
|
|
end
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2010-12-05 22:27:45 -05:00
|
|
|
def build_response(options = {})
|
2010-02-20 18:08:22 -05:00
|
|
|
Dmail.new do |dmail|
|
2013-03-03 16:05:47 -05:00
|
|
|
if title =~ /Re:/
|
|
|
|
dmail.title = title
|
|
|
|
else
|
|
|
|
dmail.title = "Re: #{title}"
|
|
|
|
end
|
2010-02-20 18:08:22 -05:00
|
|
|
dmail.owner_id = from_id
|
|
|
|
dmail.body = quoted_body
|
2010-12-05 22:27:45 -05:00
|
|
|
dmail.to_id = from_id unless options[:forward]
|
2010-02-20 18:08:22 -05:00
|
|
|
dmail.from_id = to_id
|
|
|
|
end
|
2010-11-19 16:24:17 -05:00
|
|
|
end
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2013-01-10 17:45:52 -05:00
|
|
|
module SearchMethods
|
2019-06-30 13:37:32 -04:00
|
|
|
def sent_by_id(user_id)
|
|
|
|
where("dmails.from_id = ? AND dmails.owner_id != ?", user_id, user_id)
|
|
|
|
end
|
|
|
|
|
2017-12-15 16:55:27 -05:00
|
|
|
def sent_by(user)
|
|
|
|
where("dmails.from_id = ? AND dmails.owner_id != ?", user.id, user.id)
|
|
|
|
end
|
|
|
|
|
2013-01-10 17:45:52 -05:00
|
|
|
def active
|
|
|
|
where("is_deleted = ?", false)
|
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2013-01-10 17:45:52 -05:00
|
|
|
def deleted
|
|
|
|
where("is_deleted = ?", true)
|
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2018-05-03 19:53:35 -04:00
|
|
|
def read
|
|
|
|
where(is_read: true)
|
|
|
|
end
|
|
|
|
|
2013-01-10 17:45:52 -05:00
|
|
|
def unread
|
|
|
|
where("is_read = false and is_deleted = false")
|
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2013-01-10 17:45:52 -05:00
|
|
|
def visible
|
|
|
|
where("owner_id = ?", CurrentUser.id)
|
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2013-01-10 17:45:52 -05:00
|
|
|
def search(params)
|
2017-12-17 17:58:34 -05:00
|
|
|
q = super
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2018-08-31 20:23:25 -04:00
|
|
|
q = q.attribute_matches(:title, params[:title_matches])
|
2023-02-19 14:01:54 -05:00
|
|
|
q = q.attribute_matches(:body, params[:message_matches])
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2023-08-03 16:01:53 -04:00
|
|
|
q = q.where_user(:to_id, :to, params)
|
|
|
|
q = q.where_user(:from_id, :from, params)
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2018-05-03 16:29:43 -04:00
|
|
|
q = q.attribute_matches(:is_read, params[:is_read])
|
|
|
|
q = q.attribute_matches(:is_deleted, params[:is_deleted])
|
2017-09-14 16:19:16 -04:00
|
|
|
|
2018-05-03 19:53:35 -04:00
|
|
|
q = q.read if params[:read].to_s.truthy?
|
|
|
|
q = q.unread if params[:read].to_s.falsy?
|
2014-03-29 16:28:55 -04:00
|
|
|
|
2020-03-07 15:13:12 -05:00
|
|
|
q.order(created_at: :desc)
|
2013-01-10 17:45:52 -05:00
|
|
|
end
|
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
include AddressMethods
|
|
|
|
include FactoryMethods
|
2013-01-10 17:45:52 -05:00
|
|
|
extend SearchMethods
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2019-06-27 11:33:02 -04:00
|
|
|
def user_not_limited
|
2019-06-30 13:37:32 -04:00
|
|
|
# System user must be able to send dmails at a very high rate, do not rate limit the system user.
|
2020-03-12 22:36:08 -04:00
|
|
|
return true if bypass_limits == true
|
2019-06-30 13:37:32 -04:00
|
|
|
return true if from_id == User.system.id
|
2024-08-02 10:43:07 -04:00
|
|
|
return true if from.is_janitor?
|
2023-09-17 11:57:17 -04:00
|
|
|
|
2019-06-27 11:33:02 -04:00
|
|
|
allowed = CurrentUser.can_dmail_with_reason
|
2023-09-17 11:57:17 -04:00
|
|
|
if allowed != true
|
|
|
|
errors.add(:base, "Sender #{User.throttle_reason(allowed)}")
|
|
|
|
return
|
|
|
|
end
|
2019-06-27 11:33:02 -04:00
|
|
|
minute_allowed = CurrentUser.can_dmail_minute_with_reason
|
2023-09-17 11:57:17 -04:00
|
|
|
if minute_allowed != true
|
|
|
|
errors.add(:base, "Please wait a bit before trying to send again")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
day_allowed = CurrentUser.can_dmail_day_with_reason
|
|
|
|
if day_allowed != true
|
|
|
|
errors.add(:base, "Sender #{User.throttle_reason(day_allowed, 'daily')}")
|
|
|
|
return
|
2019-06-27 11:33:02 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-10-03 10:29:49 -04:00
|
|
|
def recipient_accepts_dmails
|
2020-05-05 22:58:15 -04:00
|
|
|
unless to
|
|
|
|
errors.add(:to_name, "not found")
|
|
|
|
return false
|
|
|
|
end
|
2020-09-06 10:28:30 -04:00
|
|
|
return true if from_id == User.system.id
|
|
|
|
return true if from.is_janitor?
|
2019-10-03 10:29:49 -04:00
|
|
|
if to.disable_user_dmails
|
|
|
|
errors.add(:to_name, "has disabled DMails")
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
if from.disable_user_dmails && !to.is_janitor?
|
|
|
|
errors.add(:to_name, "is not a valid recipient while blocking DMails from others. You may only message janitors and above")
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
if to.is_blacklisting_user?(from)
|
|
|
|
errors.add(:to_name, "does not wish to receive DMails from you")
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
def quoted_body
|
2019-08-18 04:50:43 -04:00
|
|
|
"[quote]\n#{from.pretty_name} said:\n\n#{body}\n[/quote]\n\n"
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2017-12-28 19:50:08 -05:00
|
|
|
def send_email
|
2022-03-05 10:05:53 -05:00
|
|
|
if to.receive_email_notifications? && to.email =~ /@/ && owner_id == to.id
|
2015-08-18 20:37:07 -04:00
|
|
|
UserMailer.dmail_notice(self).deliver_now
|
2013-03-19 08:10:10 -04:00
|
|
|
end
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
def mark_as_read!
|
2018-05-09 14:56:01 -04:00
|
|
|
update_column(:is_read, true)
|
2024-02-23 11:18:22 -05:00
|
|
|
owner.update(unread_dmail_count: owner.dmails.unread.count)
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
2013-03-19 08:10:10 -04:00
|
|
|
|
2024-02-23 10:39:59 -05:00
|
|
|
def mark_as_unread!
|
|
|
|
update_column(:is_read, false)
|
2024-02-23 11:18:22 -05:00
|
|
|
owner.update(unread_dmail_count: owner.dmails.unread.count)
|
2024-02-23 10:39:59 -05:00
|
|
|
end
|
|
|
|
|
2017-02-23 21:15:29 -05:00
|
|
|
def is_automated?
|
2017-12-15 15:51:24 -05:00
|
|
|
from == User.system
|
2017-02-23 21:15:29 -05:00
|
|
|
end
|
|
|
|
|
2015-08-13 20:16:24 -04:00
|
|
|
def filtered?
|
|
|
|
CurrentUser.dmail_filter.try(:filtered?, self)
|
|
|
|
end
|
|
|
|
|
|
|
|
def auto_read_if_filtered
|
|
|
|
if owner_id != CurrentUser.id && to.dmail_filter.try(:filtered?, self)
|
2014-12-12 20:36:48 -05:00
|
|
|
self.is_read = true
|
2014-11-20 00:28:26 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-02-20 18:08:22 -05:00
|
|
|
def update_recipient
|
2015-09-23 15:13:14 -04:00
|
|
|
if owner_id != CurrentUser.user.id && !is_deleted? && !is_read?
|
2024-02-23 11:18:22 -05:00
|
|
|
to.update(unread_dmail_count: to.dmails.unread.count)
|
2014-11-20 00:28:26 -05:00
|
|
|
end
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|
2019-08-23 19:59:28 -04:00
|
|
|
|
2019-03-14 01:55:52 -04:00
|
|
|
def visible_to?(user)
|
2022-11-28 10:21:40 -05:00
|
|
|
return true if user.is_moderator? && (from_id == User.system.id || Ticket.exists?(qtype: "dmail", disp_id: id))
|
|
|
|
return true if user.is_admin? && (to.is_admin? || from.is_admin?)
|
|
|
|
owner_id == user.id
|
2013-06-23 12:12:30 -04:00
|
|
|
end
|
2010-02-20 18:08:22 -05:00
|
|
|
end
|