class Message < ApplicationRecord belongs_to :user belongs_to :chat_channel validates :message_html, presence: true validates :message_markdown, presence: true, length: { maximum: 1024 } validate :channel_permission before_validation :determine_user_validity before_validation :evaluate_markdown after_create :send_email_if_appropriate after_create :update_chat_channel_last_message_at after_create :update_all_has_unopened_messages_statuses def preferred_user_color color_options = [user.bg_color_hex || "#000000", user.text_color_hex || "#000000"] HexComparer.new(color_options).brightness(0.9) end def direct_receiver return if chat_channel.channel_type != "direct" chat_channel.users.where.not(id: user.id).first end private def update_chat_channel_last_message_at chat_channel.touch(:last_message_at) chat_channel.index! chat_channel.chat_channel_memberships.reindex! ChatChannels::IndexJob.perform_later(chat_channel_id: chat_channel.id) end def update_all_has_unopened_messages_statuses chat_channel. chat_channel_memberships. where("last_opened_at < ?", 10.seconds.ago). where. not(user_id: user_id). update_all(has_unopened_messages: true) end def evaluate_markdown html = MarkdownParser.new(message_markdown).evaluate_markdown html = append_rich_links(html) self.message_html = html end def append_rich_links(html) doc = Nokogiri::HTML(html) doc.css("a").each do |anchor| if (article = rich_link_article(anchor)) html += " #{"
" if article.main_image.present?}

#{article.title}

#{article.cached_user.name}・#{article.readable_publish_date || 'Draft Post'}

".html_safe elsif (tag = rich_link_tag(anchor)) html += "

#{"" if tag.badge_id.present?} ##{tag.name}

".html_safe elsif (user = rich_user_link(anchor)) html += "

#{user.name}

".html_safe end end html end def cl_path(img_src) ActionController::Base.helpers. cl_image_path(img_src, type: "fetch", width: 725, crop: "limit", flags: "progressive", fetch_format: "auto", sign_url: true) end def determine_user_validity return unless chat_channel user_ok = chat_channel.status == "active" && (chat_channel.has_member?(user) || chat_channel.channel_type == "open") errors.add(:base, "You are not a participant of this chat channel.") unless user_ok end def channel_permission errors.add(:base, "Must be part of channel.") if chat_channel_id.blank? channel = ChatChannel.find(chat_channel_id) return if channel.open? errors.add(:base, "You are not a participant of this chat channel.") unless channel.has_member?(user) errors.add(:base, "Something went wrong") if channel.status == "blocked" end def rich_link_article(link) Article.find_by(slug: link["href"].split("/")[4].split("?")[0]) if link["href"].include?("//#{ApplicationConfig['APP_DOMAIN']}/") && link["href"].split("/")[4] end def rich_link_tag(link) Tag.find_by(name: link["href"].split("/t/")[1].split("/")[0]) if link["href"].include?("//#{ApplicationConfig['APP_DOMAIN']}/t/") end def rich_user_link(link) User.find_by(username: link["href"].split("/")[3].split("/")[0]) if link["href"].include?("//#{ApplicationConfig['APP_DOMAIN']}/") end def send_email_if_appropriate recipient = direct_receiver return if !chat_channel.direct? || recipient.updated_at > 1.hour.ago || recipient.chat_channel_memberships.order("last_opened_at DESC"). first.last_opened_at > 15.hours.ago || chat_channel.last_message_at > 30.minutes.ago || recipient.email_connect_messages == false NotifyMailer.new_message_email(self).deliver end end