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
|