104 lines
3.2 KiB
Ruby
104 lines
3.2 KiB
Ruby
class ScrapeTogglJob < ApplicationJob
|
|
queue_as :default
|
|
|
|
def perform(*args)
|
|
courses = Course.all
|
|
|
|
courses.each do |course|
|
|
self.scrape_course(course)
|
|
end
|
|
end
|
|
|
|
# @param [Course] course
|
|
def scrape_course(course)
|
|
toggl_project_id = course.toggl_project
|
|
lectures = course.lectures.order(:start_time).includes(:tracked_time_entries)
|
|
|
|
return if lectures.empty?
|
|
|
|
entries_data = Toggl::entries_for_project(
|
|
toggl_project_id,
|
|
|
|
# TODO: Work out better limits
|
|
start_time: Time.new('2023-01-01'),
|
|
end_time: Time.new('2024-01-01')
|
|
)
|
|
|
|
puts("Entries data for #{course.title}: #{entries_data}")
|
|
|
|
return if entries_data.empty?
|
|
|
|
entries_data.each do |entry|
|
|
entry_title = entry['description']
|
|
|
|
# Skip if we've already seen this entry, NOTE: we assume that there is only one inner_entry per time entry
|
|
next if TrackedTimeEntry.exists?(associated_toggl_entry_id: entry['time_entries'][0]['id'])
|
|
|
|
if (lecture = lectures.find_by(title: entry_title))
|
|
is_concurrent = entry['time_entries'].any? do |inner_entry|
|
|
(Time.new(inner_entry['start']) - lecture.start_time).abs < 10.minutes
|
|
end
|
|
|
|
kind = if is_concurrent
|
|
:concurrent
|
|
else
|
|
:catchup
|
|
end
|
|
|
|
lecture.tracked_time_entries.create!(
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
|
|
# TODO: What should happen if the time entry is materially before the lecture?
|
|
kind:
|
|
) and next
|
|
elsif (work_item = course.work_items.find_by(title: entry_title))
|
|
work_item.tracked_time_entries.create!(
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
kind: :generic
|
|
) and next
|
|
end
|
|
|
|
concurrent_unlabeled = entry['time_entries'].any? do |inner_entry|
|
|
lecture = lectures.find do |lecture|
|
|
(Time.new(inner_entry['start']) - lecture.start_time).abs < 10.minutes
|
|
end
|
|
|
|
if lecture.present?
|
|
lecture.tracked_time_entries.create!(
|
|
kind: :concurrent,
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: inner_entry['id']
|
|
)
|
|
end
|
|
|
|
lecture.present?
|
|
end
|
|
|
|
next if concurrent_unlabeled
|
|
|
|
preparation_regex = /^(.+): ?(?:Prep|Preparation)?$/
|
|
review_regex = /^(.+): ?(?:Review|Recap)/
|
|
|
|
if (lecture_title_match = entry_title.match(preparation_regex)) and (lecture = lectures.find_by(title: lecture_title_match[1]))
|
|
lecture.tracked_time_entries.create!(
|
|
kind: :preparation,
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
)
|
|
|
|
broadcast_update_to lecture, :status
|
|
elsif (lecture_title_match = entry_title.match(review_regex)) and (lecture = lectures.find_by(title: lecture_title_match[1]))
|
|
lecture.tracked_time_entries.create!(
|
|
kind: :review,
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
)
|
|
|
|
broadcast_update_to lecture, :status
|
|
end
|
|
end
|
|
end
|
|
end
|