From 4ae6acc878466ab74ba4302b0bbebd3f348cb1ec Mon Sep 17 00:00:00 2001
From: Felix Eckhofer <felix@eckhofer.com>
Date: Sun, 22 Dec 2024 19:56:35 +0100
Subject: [PATCH] Deal with canceled talks

When talks are removed from Fahrplan, move them to a dummy stage.
---
 app/jobs/pretalx/import_job.rb | 20 ++++++++++++++++++++
 app/models/user.rb             |  3 ++-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/app/jobs/pretalx/import_job.rb b/app/jobs/pretalx/import_job.rb
index 3b94aab..58ebf3c 100644
--- a/app/jobs/pretalx/import_job.rb
+++ b/app/jobs/pretalx/import_job.rb
@@ -13,6 +13,10 @@ module Pretalx
       response.success? or return Rails.logger.error "Failed to fetch schedule from #{url}"
 
       schedule = JSON.parse(response.body)
+      return Rails.logger.error "Incomplete JSON received from #{url}" unless
+        schedule.dig('schedule', 'conference', 'rooms') &&
+        schedule.dig('schedule', 'conference', 'days')
+
       # We keep a local hash of the stages, because the sessions reference stages by name instead of id
       stages = {}
       schedule['schedule']['conference']['rooms'].each do |stage_data|
@@ -21,10 +25,21 @@ module Pretalx
           stage_.save!
         end
       end
+
+      # This is where canceled sessions are moved to, so we can still easily access them
+      canceled_stage = Stage.find_or_initialize_by(conference:, ref_id: 'c3lingo_canceled').tap do |stage_|
+        stage_.name = 'Canceled talk'
+        stage_.description = 'A dummy stage where talks move to when the disappear from the Fahrplan'
+        stage_.save!
+      end
+
+      # We build a list of sessions that exist in the current version of the fahrplan. That way we can move removed sessions to the "Canceled session" fake stage.
+      sessions = []
       schedule['schedule']['conference']['days'].each do |day_data|
         day_data['rooms'].each do |stage_name, stage_data|
           stage = stages[stage_name]
           stage_data.each do |session_data|
+            sessions << session_data['guid']
             Session.find_or_initialize_by(conference:, ref_id: session_data['guid']).tap do |session|
               session.stage = stage
               session.title = session_data['title']
@@ -48,6 +63,11 @@ module Pretalx
           end
         end
       end
+
+      Session.where(conference:).where.not(ref_id: sessions).each do |canceled|
+        canceled.stage = canceled_stage
+        canceled.save!
+      end
     end
 
     def perform(conference_slug, *args)
diff --git a/app/models/user.rb b/app/models/user.rb
index c59c5b3..867e3ad 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -50,7 +50,8 @@ class User < ApplicationRecord
 
   private
 
-  def valid_invitation_token valid_tokens = ["gargamel"]
+  def valid_invitation_token
+    valid_tokens = ["gargamel"]
     errors.add(:invitation_token, "is invalid") unless valid_tokens.include?(invitation_token)
   end
 end
-- 
GitLab