From a112c4cb7a6595a135626f651a5df0db62a19575 Mon Sep 17 00:00:00 2001
From: Felix Eckhofer <felix@eckhofer.com>
Date: Mon, 30 Dec 2024 13:51:15 +0100
Subject: [PATCH] Link session back to engelsystem

---
 app/jobs/pretalx/import_job.rb                | 51 +++++++++++++++++--
 app/views/assignments/by_user.html.erb        |  4 +-
 app/views/assignments/index.html.erb          |  2 +-
 .../shared/_session_engelsystem.html.erb      |  1 +
 ...28154120_add_engelsystem_id_to_sessions.rb |  5 ++
 ...0120900_add_engelsystem_url_to_sessions.rb |  5 ++
 db/schema.rb                                  |  4 +-
 db/seeds.rb                                   |  6 ++-
 8 files changed, 68 insertions(+), 10 deletions(-)
 create mode 100644 app/views/shared/_session_engelsystem.html.erb
 create mode 100644 db/migrate/20241228154120_add_engelsystem_id_to_sessions.rb
 create mode 100644 db/migrate/20241230120900_add_engelsystem_url_to_sessions.rb

diff --git a/app/jobs/pretalx/import_job.rb b/app/jobs/pretalx/import_job.rb
index 12956a7..1ddfbff 100644
--- a/app/jobs/pretalx/import_job.rb
+++ b/app/jobs/pretalx/import_job.rb
@@ -75,9 +75,35 @@ module Pretalx
       end
     end
 
+    def import_engelsystem_refs(conference, engelsystem_url)
+      return unless data = fetch_engelsystem(engelsystem_url, "angeltypes/34/shifts")
+      shifts = data.each_with_object({}) do |shift, hash|
+        starts_at = parse_datetime_or_nil(conference, shift['starts_at'])
+        if hash[starts_at].nil?
+          hash[starts_at] = [shift]
+        else
+          hash[starts_at].push(shift)
+        end
+      end
+      Session.joins(:conference).where(conference:).each do |session|
+        shifts_at_time = shifts[session.starts_at - 15.minutes]
+        unless shifts_at_time.nil?
+          shifts_at_time.each do |shift|
+            if session.stage.name == shift.dig("location", "name")
+              session.engelsystem_id = shift["id"]
+              session.engelsystem_url = shift["url"]
+              session.save
+              break
+            end
+          end
+        end
+      end
+    end
+
     def perform(conference_slug, *args)
       conference = Conference.find_by(slug: conference_slug)
       import_schedule(conference, conference.data['schedule_url'], conference.data['filedrop_url'])
+      import_engelsystem_refs(conference, conference.data['engelsystem_url'])
       RevisionSet.create!(conference:)
 
       heartbeat = conference.data['heartbeat_url']
@@ -86,6 +112,23 @@ module Pretalx
 
     private
 
+    def fetch_engelsystem(engelsystem_url, endpoint)
+      begin
+        response = HTTParty.get(
+          engelsystem_url + endpoint,
+          headers: {
+            'Accept' => 'application/json',
+            "x-api-key" => fetch_credential("engelsystem_token")
+          },
+          timeout: 10
+        )
+        return response.success? ? JSON.parse(response.body)["data"] : nil
+      rescue => e
+        Rails.logger.warn("Engelsystem response for #{endpoint} failed: #{e.message}")
+        return nil
+      end
+    end
+
     def fetch_filedrop_index(filedrop_url)
       return {} unless filedrop_url
 
@@ -125,7 +168,7 @@ module Pretalx
       # Add or update comments
       filedrop_data["comments"]&.each do |comment_data|
         session.filedrop_comments.find_or_initialize_by(body: comment_data['body']).tap do |comment|
-          comment.orig_created = parse_datetime_or_nil(comment_data['meta']['created'])
+          comment.orig_created = parse_datetime_or_nil(session.conference, comment_data['meta']['created'])
           comment.save!
         end
       end
@@ -142,7 +185,7 @@ module Pretalx
       filedrop_data['files']&.each do |file_data|
         session.filedrop_files.find_or_initialize_by(name: file_data['name'], checksum: file_data['meta']['hash']).tap do |file|
           file.size = file_data['meta']['size']
-          file.orig_created = parse_datetime_or_nil(file_data['meta']['created'])
+          file.orig_created = parse_datetime_or_nil(session.conference, file_data['meta']['created'])
           unless file_data['url'].blank?
             file.download(filedrop_url + file_data['url'].sub(/\A\//, ''))
             file.save
@@ -153,8 +196,8 @@ module Pretalx
       end
     end
 
-    def parse_datetime_or_nil(datetime_string)
-      DateTime.iso8601(datetime_string)
+    def parse_datetime_or_nil(conference, datetime_string)
+      DateTime.iso8601(datetime_string).in_time_zone(conference.time_zone)
     rescue
       nil
     end
diff --git a/app/views/assignments/by_user.html.erb b/app/views/assignments/by_user.html.erb
index d0576f2..bb5542c 100644
--- a/app/views/assignments/by_user.html.erb
+++ b/app/views/assignments/by_user.html.erb
@@ -13,7 +13,7 @@
         <% assignments_on_date.each do |assignment| %>
           <li class="<%= assignment.session.starts_at < now ? "past" : "future" %>">
             <span class="tabular-nums"><%= assignment.session.starts_at.strftime('%H:%M') %> &ndash; <%= assignment.session.ends_at.strftime('%H:%M') %></span>:
-            <%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %><%= link_to assignment.session.title, conference_session_path(assignment.session.conference, assignment.session) %> @ <%= assignment.session.stage.name %>
+            <%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %><%= link_to assignment.session.title, conference_session_path(assignment.session.conference, assignment.session) %> @ <%= assignment.session.stage.name %><%= render partial: 'shared/session_engelsystem', locals: { session: assignment.session } %>
             <small><% assignment.session.assignments.map(&:user).each do |other_user| %>
               <%= render partial: 'application/user_avatar', locals: { user: other_user } %>
             <% end %></small>
@@ -43,7 +43,7 @@
         <td><%= assignment.session.starts_at.strftime('%H:%M') %></td>
         <td><%= assignment.session.ends_at.strftime('%H:%M') %></td>
         <td><%= assignment.session.stage.name %></td>
-        <td><%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %><%= link_to assignment.session.title, assignment.session.url, target: "_blank" %></td>
+        <td><%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %><%= link_to assignment.session.title, assignment.session.url, target: "_blank" %><%= render partial: 'shared/session_engelsystem', locals: { session: assignment.session } %></td>
         <td><% assignment.session.assignments.map(&:user).each do |other_user| %><%= render partial: 'application/user_avatar', locals: { user: other_user } %><% end %></td>
       </tr>
     <% end %>
diff --git a/app/views/assignments/index.html.erb b/app/views/assignments/index.html.erb
index b7f9018..470a815 100644
--- a/app/views/assignments/index.html.erb
+++ b/app/views/assignments/index.html.erb
@@ -20,7 +20,7 @@
             <% assignments_on_date.each do |assignment| %>
               <li class="<%= assignment.session.starts_at < now ? "past" : "future" %>">
                 <span class="tabular-nums"><%= assignment.session.starts_at.strftime('%H:%M') %> &ndash; <%= assignment.session.ends_at.strftime('%H:%M') %></span>:
-                <%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %><%= link_to assignment.session.title, conference_session_path(assignment.session.conference, assignment.session) %> @ <%= assignment.session.stage.name %>
+                <%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %><%= link_to assignment.session.title, conference_session_path(assignment.session.conference, assignment.session) %><%= render partial: 'shared/session_engelsystem', locals: { session: assignment.session } %> @ <%= assignment.session.stage.name %>
                 <small><% assignment.session.assignments.map(&:user).each do |other_user| %>
                   <%= render partial: 'application/user_avatar', locals: { user: other_user } %>
                 <% end %></small>
diff --git a/app/views/shared/_session_engelsystem.html.erb b/app/views/shared/_session_engelsystem.html.erb
new file mode 100644
index 0000000..bac8d07
--- /dev/null
+++ b/app/views/shared/_session_engelsystem.html.erb
@@ -0,0 +1 @@
+<% unless session.engelsystem_url.blank? %><%= link_to session.engelsystem_url, target: "_blank", aria_label: "Engelsystem", title: "Engelsystem" do %><svg class="inline-block w-5 h-5 mx-1 pb-0.5" xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" viewBox="0 0 500 500"><g transform="rotate(180 255.7 239.5)"><path d="m262.16 408.63c-70.507 0-127.66-66.46-127.66-148.44 0-45.996 17.956-87.059 46.202-114.29v-34.156l-179.95-52.779v-100.51l510.58-0.01416 0.0743 96.124-165.36 59.377h-2.432v31.957c28.247 27.228 46.202 68.291 46.202 114.29 0 81.983-57.157 148.44-127.66 148.44zm0 70.373c-124.23 0-224.93-40.861-224.93-91.265s100.71-91.265 224.93-91.265 224.93 40.861 224.93 91.265-100.71 91.265-224.93 91.265zm0-46.182c102.74 0 186.02-28.553 186.02-63.775s-83.286-63.776-186.02-63.776c-102.74 0-186.02 28.553-186.02 63.776s83.286 63.775 186.02 63.775z"/></g></svg><% end %><% end %>
diff --git a/db/migrate/20241228154120_add_engelsystem_id_to_sessions.rb b/db/migrate/20241228154120_add_engelsystem_id_to_sessions.rb
new file mode 100644
index 0000000..5bcf4ae
--- /dev/null
+++ b/db/migrate/20241228154120_add_engelsystem_id_to_sessions.rb
@@ -0,0 +1,5 @@
+class AddEngelsystemIdToSessions < ActiveRecord::Migration[7.1]
+  def change
+    add_column :sessions, :engelsystem_id, :integer
+  end
+end
diff --git a/db/migrate/20241230120900_add_engelsystem_url_to_sessions.rb b/db/migrate/20241230120900_add_engelsystem_url_to_sessions.rb
new file mode 100644
index 0000000..6520ae6
--- /dev/null
+++ b/db/migrate/20241230120900_add_engelsystem_url_to_sessions.rb
@@ -0,0 +1,5 @@
+class AddEngelsystemUrlToSessions < ActiveRecord::Migration[7.1]
+  def change
+    add_column :sessions, :engelsystem_url, :string
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8af166c..707b098 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.1].define(version: 2024_12_26_172555) do
+ActiveRecord::Schema[7.1].define(version: 2024_12_30_120900) do
   create_table "assignments", force: :cascade do |t|
     t.integer "user_id", null: false
     t.integer "session_id", null: false
@@ -159,6 +159,8 @@ ActiveRecord::Schema[7.1].define(version: 2024_12_26_172555) do
     t.string "ref_id"
     t.string "notes"
     t.boolean "recorded", default: true, null: false
+    t.integer "engelsystem_id"
+    t.string "engelsystem_url"
     t.index ["conference_id"], name: "index_sessions_on_conference_id"
     t.index ["ref_id", "conference_id"], name: "index_sessions_on_ref_id_and_conference_id", unique: true
     t.index ["stage_id"], name: "index_sessions_on_stage_id"
diff --git a/db/seeds.rb b/db/seeds.rb
index f2d14f2..ae39fcb 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -57,7 +57,8 @@ Conference.find_or_create_by(slug: "38c3").tap do |c|
   c.data = {
     "heartbeat_url" => fetch_credential("heartbeat_deen"),
     "schedule_url" => "https://api.events.ccc.de/congress/2024/assembly/6840c453-af5c-413c-8127-adcbdcd98e9e/schedule.json",
-    "filedrop_url" => "https://speakers.c3lingo.org/"
+    "filedrop_url" => "https://speakers.c3lingo.org/",
+    "engelsystem_url" => "https://engel.events.ccc.de/api/v0-beta/"
   }
   c.import_job_class = "pretalx"
   c.location = "Congress Center Hamburg"
@@ -73,7 +74,8 @@ Conference.find_or_create_by(slug: "38c3-more").tap do |c|
   c.data = {
     "heartbeat_url" => fetch_credential("heartbeat_more"),
     "schedule_url" => "https://api.events.ccc.de/congress/2024/assembly/6840c453-af5c-413c-8127-adcbdcd98e9e/schedule.json",
-    "filedrop_url" => "https://speakers.c3lingo.org/"
+    "filedrop_url" => "https://speakers.c3lingo.org/",
+    "engelsystem_url" => "https://engel.events.ccc.de/api/v0-beta/"
   }
   c.import_job_class = "pretalx"
   c.location = "Congress Center Hamburg"
-- 
GitLab