discourse-calendar/db/migrate/20201111005205_move_data_to...

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