diff --git a/app/models/dmail.rb b/app/models/dmail.rb new file mode 100644 index 000000000..376c9a3fd --- /dev/null +++ b/app/models/dmail.rb @@ -0,0 +1,94 @@ +class Dmail < ActiveRecord::Base + validates_presence_of :to_id + validates_presence_of :from_id + validates_format_of :title, :with => /\S/ + validates_format_of :body, :with => /\S/ + belongs_to :owner, :class_name => "User" + belongs_to :to, :class_name => "User" + belongs_to :from, :class_name => "User" + after_create :update_recipient + after_create :send_dmail + attr_accessible :title, :body, :is_deleted + scope :for, lambda {|user| where(["owner_id = ?", user])} + scope :inbox, where("to_id = owner_id") + scope :sent, where("from_id = owner_id") + scope :active, where(["is_deleted = ?", false]) + scope :deleted, where(["is_deleted = ?", true]) + scope :search_message, lambda {|query| where(["message_index @@ plainto_tsquery(?)", query])} + + module AddressMethods + def to_name + User.find_pretty_name(to_id) + end + + def from_name + User.find_pretty_name(from_id) + end + + def to_name=(name) + user = User.find_by_name(name) + return if user.nil? + self.to_id = user.id + end + + def from_name=(name) + user = User.find_by_name(name) + return if user.nil? + self.from_id = user.id + end + end + + module FactoryMethods + module ClassMethods + def create_new(dmail) + copy = dmail.clone + copy.owner_id = dmail.to_id + copy.save + + copy = dmail.clone + copy.owner_id = dmail.from_id + copy.save + end + end + + def self.included(m) + m.extend(ClassMethods) + end + + def build_response + Dmail.new do |dmail| + dmail.title = "Re: #{title}" + dmail.owner_id = from_id + dmail.body = quoted_body + dmail.to_id = from_id + dmail.from_id = to_id + dmail.parent_id = id + end + end + end + + include AddressMethods + include FactoryMethods + + def quoted_body + "[quote]#{body}[/quote]" + end + + def send_dmail + if to.receive_email_notifications? && to.email.include?("@") + UserMailer.dmail_notice(self).deliver + end + end + + def mark_as_read! + update_attribute(:is_read, true) + + unless Dmail.exists?(["to_id = ? AND is_read = false", to_id]) + to.update_attribute(:has_mail, false) + end + end + + def update_recipient + to.update_attribute(:has_mail, true) + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 73bbe238d..c8e3c6d54 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -23,6 +23,10 @@ class User < ActiveRecord::Base select_value_sql("SELECT name FROM users WHERE id = ?", user_id) || Danbooru.config.default_guest_name end end + + def find_pretty_name(user_id) + find_name.tr("_", " ") + end end def self.included(m) diff --git a/app/models/user_mailer.rb b/app/models/user_mailer.rb new file mode 100644 index 000000000..1f464f845 --- /dev/null +++ b/app/models/user_mailer.rb @@ -0,0 +1,24 @@ +class UserMailer < ActionMailer::Base + default :host => Danbooru.config.server_host, :from => Danbooru.config.contact_email, :content_type => "text/html" + + def password_reset(user, new_password) + @user = user + @new_password = new_password + mail(:to => @user.email, :subject => "#{Danbooru.config.app_name} - Password Reset") + end + + def name_reminder(user) + @user = user + mail(:to => user.email, :subject => "#{Danbooru.config.app_name} - Name Reminder") + end + + def deletion(user) + @user = user + mail(:to => user.email, :subject => "#{}") + end + + def dmail_notice(dmail) + @dmail = dmail + mail(:to => dmail.to.email, :subject => "#{Danbooru.config.app_name} - Message received from #{dmail.from.name}") + end +end diff --git a/app/views/user_mailer/dmail.html.erb b/app/views/user_mailer/dmail.html.erb new file mode 100644 index 000000000..da309e93d --- /dev/null +++ b/app/views/user_mailer/dmail.html.erb @@ -0,0 +1,5 @@ +
<%= h @dmail.fromr.name %> said:
+ +' + end + + when "[/quote]" + if options[:inline] + "" + else + '' + end + + else + '
' + parse_inline(block) + "
" + end + end + + html.join("") + end + + module_function :parse_inline + module_function :parse_list + module_function :parse +end + diff --git a/test/factories/dmail.rb b/test/factories/dmail.rb new file mode 100644 index 000000000..f49f4444c --- /dev/null +++ b/test/factories/dmail.rb @@ -0,0 +1,8 @@ +Factory.define(:dmail) do |f| + f.owner {|x| x.association(:user)} + f.from_id {|x| x.owner_id} + f.to {|x| x.association(:user)} + f.title {Faker::Lorem.words} + f.body {Faker::Lorem.sentences} + f.is_read false +end diff --git a/test/fixtures/dmails.yml b/test/fixtures/dmails.yml new file mode 100644 index 000000000..289334110 --- /dev/null +++ b/test/fixtures/dmails.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/unit/dmail_test.rb b/test/unit/dmail_test.rb new file mode 100644 index 000000000..8a6f6fe5e --- /dev/null +++ b/test/unit/dmail_test.rb @@ -0,0 +1,75 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class DmailTest < ActiveSupport::TestCase + context "A dmail" do + setup do + MEMCACHE.flush_all + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + end + + context "search" do + should "return results based on title contents" do + dmail = Factory.create(:dmail, :title => "xxx") + matches = Dmail.search_message("xxx") + assert(matches.any?) + matches = Dmail.search_message("aaa") + assert(matches.empty?) + end + + should "return results based on body contents" do + dmail = Factory.create(:dmail, :body => "xxx") + matches = Dmail.search_message("xxx") + assert(matches.any?) + matches = Dmail.search_message("aaa") + assert(matches.empty?) + end + end + + should "should parse user names" do + user = Factory.create(:user) + dmail = Factory.build(:dmail) + dmail.to_id = nil + dmail.to_name = user.name + assert(dmail.to_id == user.id) + end + + should "construct a response" do + dmail = Factory.create(:dmail) + response = dmail.build_response + assert_equal("Re: #{dmail.title}", response.title) + assert_equal(dmail.id, response.parent_id) + assert_equal(dmail.from_id, response.to_id) + assert_equal(dmail.to_id, response.from_id) + end + + should "create a copy for each user" do + dmail = Factory.build(:dmail) + assert_difference("Dmail.count", 2) do + Dmail.create_new(dmail) + end + end + + should "send an email if the user wants it" do + user = Factory.create(:user, :receive_email_notifications => true) + assert_difference("ActionMailer::Base.deliveries.size", 1) do + Factory.create(:dmail, :to => user) + end + end + + should "be marked as read after the user reads it" do + dmail = Factory.create(:dmail) + assert(!dmail.is_read?) + dmail.mark_as_read! + assert(dmail.is_read?) + end + + should "notify the recipient he has mail" do + dmail = Factory.create(:dmail) + assert(dmail.to(true).has_mail?) + dmail.mark_as_read! + assert(!dmail.to(true).has_mail?) + end + end +end diff --git a/tmp/test-large.jpg b/tmp/test-large.jpg new file mode 100644 index 000000000..c27382e5f Binary files /dev/null and b/tmp/test-large.jpg differ diff --git a/tmp/test.jpg b/tmp/test.jpg new file mode 100644 index 000000000..253c508d9 Binary files /dev/null and b/tmp/test.jpg differ