122 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| # == Schema Information
 | |
| #
 | |
| # Table name: announcements
 | |
| #
 | |
| #  id           :bigint(8)        not null, primary key
 | |
| #  text         :text             default(""), not null
 | |
| #  published    :boolean          default(FALSE), not null
 | |
| #  all_day      :boolean          default(FALSE), not null
 | |
| #  scheduled_at :datetime
 | |
| #  starts_at    :datetime
 | |
| #  ends_at      :datetime
 | |
| #  created_at   :datetime         not null
 | |
| #  updated_at   :datetime         not null
 | |
| #  published_at :datetime
 | |
| #  status_ids   :bigint(8)        is an Array
 | |
| #
 | |
| 
 | |
| class Announcement < ApplicationRecord
 | |
|   scope :unpublished, -> { where(published: false) }
 | |
|   scope :published, -> { where(published: true) }
 | |
|   scope :chronological, -> { order(coalesced_chronology_timestamps.asc) }
 | |
|   scope :reverse_chronological, -> { order(coalesced_chronology_timestamps.desc) }
 | |
| 
 | |
|   has_many :announcement_mutes, dependent: :destroy
 | |
|   has_many :announcement_reactions, dependent: :destroy
 | |
| 
 | |
|   validates :text, presence: true
 | |
|   validates :starts_at, presence: true, if: :ends_at?
 | |
|   validates :ends_at, presence: true, if: :starts_at?
 | |
| 
 | |
|   before_validation :set_published, on: :create
 | |
| 
 | |
|   class << self
 | |
|     def coalesced_chronology_timestamps
 | |
|       Arel.sql(
 | |
|         <<~SQL.squish
 | |
|           COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at)
 | |
|         SQL
 | |
|       )
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def to_log_human_identifier
 | |
|     text
 | |
|   end
 | |
| 
 | |
|   def publish!
 | |
|     update!(published: true, published_at: Time.now.utc, scheduled_at: nil)
 | |
|   end
 | |
| 
 | |
|   def unpublish!
 | |
|     update!(published: false, scheduled_at: nil)
 | |
|   end
 | |
| 
 | |
|   def mentions
 | |
|     @mentions ||= Account.from_text(text)
 | |
|   end
 | |
| 
 | |
|   def statuses
 | |
|     @statuses ||= begin
 | |
|       if status_ids.nil?
 | |
|         []
 | |
|       else
 | |
|         Status.with_includes.distributable_visibility.where(id: status_ids)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def tags
 | |
|     @tags ||= Tag.find_or_create_by_names(Extractor.extract_hashtags(text))
 | |
|   end
 | |
| 
 | |
|   def emojis
 | |
|     @emojis ||= CustomEmoji.from_text(text)
 | |
|   end
 | |
| 
 | |
|   def reactions(account = nil)
 | |
|     grouped_ordered_announcement_reactions.select(
 | |
|       [:name, :custom_emoji_id, 'COUNT(*) as count'].tap do |values|
 | |
|         values << value_for_reaction_me_column(account)
 | |
|       end
 | |
|     ).to_a.tap do |records|
 | |
|       ActiveRecord::Associations::Preloader.new(records: records, associations: :custom_emoji).call
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   private
 | |
| 
 | |
|   def grouped_ordered_announcement_reactions
 | |
|     announcement_reactions
 | |
|       .group(:announcement_id, :name, :custom_emoji_id)
 | |
|       .order(
 | |
|         Arel.sql('MIN(created_at)').asc
 | |
|       )
 | |
|   end
 | |
| 
 | |
|   def value_for_reaction_me_column(account)
 | |
|     if account.nil?
 | |
|       'FALSE AS me'
 | |
|     else
 | |
|       <<~SQL.squish
 | |
|         EXISTS(
 | |
|           SELECT 1
 | |
|           FROM announcement_reactions inner_reactions
 | |
|           WHERE inner_reactions.account_id = #{account.id}
 | |
|             AND inner_reactions.announcement_id = announcement_reactions.announcement_id
 | |
|             AND inner_reactions.name = announcement_reactions.name
 | |
|         ) AS me
 | |
|       SQL
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def set_published
 | |
|     return unless scheduled_at.blank? || scheduled_at.past?
 | |
| 
 | |
|     self.published = true
 | |
|     self.published_at = Time.now.utc
 | |
|   end
 | |
| end
 |