2024-10-03 09:08:23 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
|
|
class Imports::Watcher
|
|
|
|
|
class UnsupportedSourceError < StandardError; end
|
|
|
|
|
|
|
|
|
|
WATCHED_DIR_PATH = Rails.root.join('tmp/imports/watched')
|
|
|
|
|
|
|
|
|
|
def call
|
2024-10-05 06:53:35 -04:00
|
|
|
user_directories.each do |user_email|
|
|
|
|
|
user = User.find_by(email: user_email)
|
|
|
|
|
next unless user
|
2024-10-03 09:08:23 -04:00
|
|
|
|
2024-10-05 06:53:35 -04:00
|
|
|
user_directory_path = File.join(WATCHED_DIR_PATH, user_email)
|
|
|
|
|
file_names = file_names(user_directory_path)
|
2024-10-03 09:08:23 -04:00
|
|
|
|
2024-10-05 06:53:35 -04:00
|
|
|
file_names.each do |file_name|
|
|
|
|
|
process_file(user, user_directory_path, file_name)
|
2024-10-03 09:08:23 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
2024-10-05 06:53:35 -04:00
|
|
|
def user_directories
|
|
|
|
|
Dir.entries(WATCHED_DIR_PATH).select do |entry|
|
|
|
|
|
path = File.join(WATCHED_DIR_PATH, entry)
|
|
|
|
|
File.directory?(path) && !['.', '..'].include?(entry)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2024-10-03 09:08:23 -04:00
|
|
|
def find_user(file_name)
|
|
|
|
|
email = file_name.split('_').first
|
|
|
|
|
|
|
|
|
|
User.find_by(email:)
|
|
|
|
|
end
|
|
|
|
|
|
2024-10-05 06:53:35 -04:00
|
|
|
def file_names(directory_path)
|
|
|
|
|
Dir.entries(directory_path).select do |file|
|
2024-12-16 06:13:38 -05:00
|
|
|
['.gpx', '.json', '.rec'].include?(File.extname(file))
|
2024-10-05 06:53:35 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def process_file(user, directory_path, file_name)
|
|
|
|
|
file_path = File.join(directory_path, file_name)
|
|
|
|
|
import = Import.find_or_initialize_by(user:, name: file_name)
|
|
|
|
|
|
|
|
|
|
return if import.persisted?
|
|
|
|
|
|
|
|
|
|
import.source = source(file_name)
|
|
|
|
|
import.raw_data = raw_data(file_path, import.source)
|
|
|
|
|
|
|
|
|
|
import.save!
|
|
|
|
|
|
|
|
|
|
ImportJob.perform_later(user.id, import.id)
|
|
|
|
|
end
|
|
|
|
|
|
2024-10-03 09:08:23 -04:00
|
|
|
def find_or_initialize_import(user, file_name)
|
|
|
|
|
import_name = file_name.split('_')[1..].join('_')
|
|
|
|
|
|
|
|
|
|
Import.find_or_initialize_by(user:, name: import_name)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def set_import_attributes(import, file_path, file_name)
|
|
|
|
|
source = source(file_name)
|
|
|
|
|
|
|
|
|
|
import.source = source
|
|
|
|
|
import.raw_data = raw_data(file_path, source)
|
|
|
|
|
|
|
|
|
|
import.save!
|
|
|
|
|
|
|
|
|
|
import.id
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def source(file_name)
|
|
|
|
|
case file_name.split('.').last
|
2024-12-16 06:13:38 -05:00
|
|
|
when 'json'
|
|
|
|
|
if file_name.match?(/location-history/i)
|
|
|
|
|
:google_phone_takeout
|
|
|
|
|
elsif file_name.match?(/Records/i)
|
|
|
|
|
:google_records
|
|
|
|
|
elsif file_name.match?(/\d{4}_\w+/i)
|
|
|
|
|
:google_semantic_history
|
|
|
|
|
else
|
|
|
|
|
:geojson
|
|
|
|
|
end
|
|
|
|
|
when 'rec' then :owntracks
|
|
|
|
|
when 'gpx' then :gpx
|
2024-10-03 09:08:23 -04:00
|
|
|
else raise UnsupportedSourceError, 'Unsupported source '
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def raw_data(file_path, source)
|
|
|
|
|
file = File.read(file_path)
|
|
|
|
|
|
2024-12-16 06:13:38 -05:00
|
|
|
case source
|
|
|
|
|
when :google_phone_takeout
|
|
|
|
|
GoogleMaps::PhoneTakeoutParser.new(file).call
|
|
|
|
|
when :google_semantic_history
|
|
|
|
|
GoogleMaps::SemanticHistoryParser.new(file).call
|
|
|
|
|
when :google_records
|
|
|
|
|
GoogleMaps::RecordsParser.new(file).call
|
|
|
|
|
when :owntracks
|
|
|
|
|
OwnTracks::RecParser.new(file).call
|
|
|
|
|
when :gpx
|
|
|
|
|
Hash.from_xml(file)
|
|
|
|
|
else
|
|
|
|
|
JSON.parse(file)
|
|
|
|
|
end
|
2024-10-03 09:08:23 -04:00
|
|
|
end
|
|
|
|
|
end
|