Files
danbooru/app/models/dmail.rb
evazion 24cb920608 mod reports: include reported user and message in forum post.
Also fix it so that reports against dmails include the key in the dmail
link so that mods can view the reported dmail.
2020-02-03 04:52:12 -06:00

199 lines
4.6 KiB
Ruby

require 'digest/sha1'
class Dmail < ApplicationRecord
validates_presence_of :title, :body, on: :create
validate :validate_sender_is_not_banned, on: :create
belongs_to :owner, :class_name => "User"
belongs_to :to, :class_name => "User"
belongs_to :from, :class_name => "User"
has_many :moderation_reports, as: :model
after_initialize :initialize_attributes, if: :new_record?
before_create :autoreport_spam
after_save :update_unread_dmail_count
after_commit :send_email, on: :create
api_attributes including: [:key]
scope :active, -> { where(is_deleted: false) }
scope :deleted, -> { where(is_deleted: true) }
scope :read, -> { where(is_read: true) }
scope :unread, -> { where(is_read: false) }
scope :visible, -> { where(owner: CurrentUser.user) }
scope :sent, -> { where("dmails.owner_id = dmails.from_id") }
scope :received, -> { where("dmails.owner_id = dmails.to_id") }
module AddressMethods
def to_name=(name)
self.to = User.find_by_name(name)
end
def initialize_attributes
self.from_id ||= CurrentUser.id
self.creator_ip_addr ||= CurrentUser.ip_addr
end
end
module FactoryMethods
extend ActiveSupport::Concern
module ClassMethods
def create_split(params)
copy = nil
Dmail.transaction do
# recipient's copy
copy = Dmail.new(params)
copy.owner_id = copy.to_id
copy.save unless copy.to_id == copy.from_id
# sender's copy
copy = Dmail.new(params)
copy.owner_id = copy.from_id
copy.is_read = true
copy.save
end
copy
end
def create_automated(params)
CurrentUser.as_system do
dmail = Dmail.new(from: User.system, **params)
dmail.owner = dmail.to
dmail.save
dmail
end
end
end
def build_response(options = {})
Dmail.new do |dmail|
if title =~ /Re:/
dmail.title = title
else
dmail.title = "Re: #{title}"
end
dmail.owner_id = from_id
dmail.body = quoted_body
dmail.to_id = from_id unless options[:forward]
dmail.from_id = to_id
end
end
end
module SearchMethods
def sent_by(user)
where("dmails.from_id = ? AND dmails.owner_id != ?", user.id, user.id)
end
def folder_matches(folder)
case folder
when "received"
active.received
when "unread"
active.received.unread
when "sent"
active.sent
when "deleted"
deleted
else
all
end
end
def search(params)
q = super
q = q.search_attributes(params, :to, :from, :is_read, :is_deleted, :title, :body)
q = q.text_attribute_matches(:title, params[:title_matches])
q = q.text_attribute_matches(:body, params[:message_matches], index_column: :message_index)
q = q.folder_matches(params[:folder])
q.apply_default_order(params)
end
end
concerning :AuthorizationMethods do
def verifier
@verifier ||= Danbooru::MessageVerifier.new(:dmail_link)
end
def key
verifier.generate(id)
end
def valid_key?(key)
decoded_id = verifier.verified(key)
id == decoded_id
end
def visible_to?(user, key)
owner_id == user.id || valid_key?(key)
end
end
include AddressMethods
include FactoryMethods
extend SearchMethods
def self.mark_all_as_read
unread.update(is_read: true)
end
def validate_sender_is_not_banned
if from.try(:is_banned?)
errors[:base] << "Sender is banned and cannot send messages"
end
end
def quoted_body
"[quote]\n#{from.pretty_name} said:\n\n#{body}\n[/quote]\n\n"
end
def send_email
if is_recipient? && !is_deleted? && to.receive_email_notifications? && to.email =~ /@/
UserMailer.dmail_notice(self).deliver_now
end
end
def is_automated?
from == User.system
end
def is_sender?
owner == from
end
def is_recipient?
owner == to
end
def autoreport_spam
if is_recipient? && SpamDetector.new(self).spam?
self.is_deleted = true
moderation_reports << ModerationReport.new(creator: User.system, reason: "Spam.")
end
end
def update_unread_dmail_count
return unless saved_change_to_id? || saved_change_to_is_read? || saved_change_to_is_deleted?
owner.with_lock do
unread_count = owner.dmails.active.unread.count
owner.update!(unread_dmail_count: unread_count)
end
end
def reportable_by?(user)
is_recipient? && !is_automated? && !from.is_moderator?
end
def dtext_shortlink(key: false, **options)
key ? "dmail ##{id}/#{key}" : "dmail ##{id}"
end
end