138 lines
4.0 KiB
Ruby
138 lines
4.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class MoveDataToEventDates < ActiveRecord::Migration[6.0]
|
|
VALID_OPTIONS = [:start, :end, :status, :"allowed-groups", :url, :name, :reminders, :recurrence]
|
|
|
|
def extract_events(post)
|
|
valid_options = VALID_OPTIONS.map { |o| "data-#{o}" }
|
|
|
|
valid_custom_fields = []
|
|
|
|
allowed_custom_fields =
|
|
DB
|
|
.query(
|
|
"SELECT * FROM site_settings WHERE name = 'discourse_post_event_allowed_custom_fields' LIMIT 1",
|
|
)
|
|
.first
|
|
&.value || ""
|
|
allowed_custom_fields
|
|
.split("|")
|
|
.each do |setting|
|
|
valid_custom_fields << {
|
|
original: "data-#{setting}",
|
|
normalized: "data-#{setting.gsub(/_/, "-")}",
|
|
}
|
|
end
|
|
|
|
Nokogiri
|
|
.HTML(post.cooked)
|
|
.css("div.discourse-post-event")
|
|
.map do |doc|
|
|
event = nil
|
|
doc.attributes.values.each do |attribute|
|
|
name = attribute.name
|
|
value = attribute.value
|
|
|
|
if value && valid_options.include?(name)
|
|
event ||= {}
|
|
event[name.sub("data-", "").to_sym] = CGI.escapeHTML(value)
|
|
end
|
|
|
|
valid_custom_fields.each do |valid_custom_field|
|
|
if value && valid_custom_field[:normalized] == name
|
|
event ||= {}
|
|
event[valid_custom_field[:original].sub("data-", "").to_sym] = CGI.escapeHTML(value)
|
|
end
|
|
end
|
|
end
|
|
event
|
|
end
|
|
.compact
|
|
end
|
|
|
|
def due_reminders(event)
|
|
return [] if event.reminders.blank?
|
|
event
|
|
.reminders
|
|
.split(",")
|
|
.map do |reminder|
|
|
value, unit = reminder.split(".")
|
|
|
|
allowed = %w[years months weeks days hours minutes seconds]
|
|
next if !allowed.include?(unit)
|
|
date = event.original_starts_at - value.to_i.public_send(unit)
|
|
{ description: reminder, date: date }
|
|
end
|
|
.compact
|
|
.select { |reminder| reminder[:date] <= Time.current }
|
|
.sort_by { |reminder| reminder[:date] }
|
|
end
|
|
|
|
def up
|
|
rename_column :discourse_post_event_events, :starts_at, :original_starts_at
|
|
rename_column :discourse_post_event_events, :ends_at, :original_ends_at
|
|
|
|
query = <<~SQL
|
|
SELECT * FROM discourse_post_event_events
|
|
WHERE original_ends_at IS NOT NULL
|
|
SQL
|
|
|
|
DB
|
|
.query(query)
|
|
.each do |event|
|
|
post = DB.query("SELECT * FROM posts WHERE id = #{event.id}").first
|
|
next if !post
|
|
extracted_event = extract_events(post).first
|
|
next if !extracted_event
|
|
|
|
finished_at = (event.original_ends_at < Time.current) && event.original_ends_at
|
|
event_will_start_sent_at = event.original_starts_at - 1.hours
|
|
event_started_sent_at = event.original_starts_at
|
|
reminder_counter = due_reminders(event).length
|
|
|
|
DB.exec <<~SQL
|
|
INSERT INTO discourse_calendar_post_event_dates(event_id, starts_at, ends_at, event_will_start_sent_at, event_started_sent_at, #{finished_at ? "finished_at ," : ""} reminder_counter, created_at, updated_at)
|
|
VALUES (#{event.id},
|
|
'#{event.original_starts_at}',
|
|
'#{event.original_ends_at}',
|
|
'#{event_will_start_sent_at}',
|
|
'#{event_started_sent_at}',
|
|
#{finished_at ? ("'" + finished_at.to_s + "'" + ", ") : ""}
|
|
#{reminder_counter},
|
|
now(),
|
|
now())
|
|
SQL
|
|
DB.exec <<~SQL
|
|
UPDATE discourse_post_event_events
|
|
SET original_starts_at = '#{extracted_event[:start]}', original_ends_at = '#{extracted_event[:end]}'
|
|
WHERE id = #{event.id}
|
|
SQL
|
|
end
|
|
|
|
begin
|
|
Jobs.cancel_scheduled_job(:discourse_post_event_send_reminder)
|
|
rescue StandardError
|
|
nil
|
|
end
|
|
begin
|
|
Jobs.cancel_scheduled_job(:discourse_post_event_event_started)
|
|
rescue StandardError
|
|
nil
|
|
end
|
|
begin
|
|
Jobs.cancel_scheduled_job(:discourse_post_event_event_will_start)
|
|
rescue StandardError
|
|
nil
|
|
end
|
|
begin
|
|
Jobs.cancel_scheduled_job(:discourse_post_event_event_ended)
|
|
rescue StandardError
|
|
nil
|
|
end
|
|
end
|
|
|
|
def down
|
|
raise ActiveRecord::IrreversibleMigration
|
|
end
|
|
end
|