diff --git a/.gitignore b/.gitignore index b3803267..9583fb0a 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,9 @@ .DS_Store .env +.byebug_history + + .devcontainer/.onCreateCommandMarker .devcontainer/.postCreateCommandMarker .devcontainer/.updateContentCommandMarker diff --git a/app/jobs/import_job.rb b/app/jobs/import_job.rb index a07cfa46..5cad02b6 100644 --- a/app/jobs/import_job.rb +++ b/app/jobs/import_job.rb @@ -4,9 +4,11 @@ class ImportJob < ApplicationJob queue_as :imports def perform(user_id, import_id) + user = User.find(user_id) import = user.imports.find(import_id) import.process! + end end diff --git a/app/services/imports/watcher.rb b/app/services/imports/watcher.rb index 43f3653b..4ea6c07b 100644 --- a/app/services/imports/watcher.rb +++ b/app/services/imports/watcher.rb @@ -4,16 +4,19 @@ class Imports::Watcher class UnsupportedSourceError < StandardError; end WATCHED_DIR_PATH = Rails.root.join('tmp/imports/watched') + SUPPORTED_FORMATS = %w[.gpx .json .rec].freeze def call user_directories.each do |user_email| user = User.find_by(email: user_email) next unless user +puts "Processing directory for user: #{user.email}" user_directory_path = File.join(WATCHED_DIR_PATH, user_email) file_names = file_names(user_directory_path) file_names.each do |file_name| + puts "Processing file: #{file_name}" process_file(user, user_directory_path, file_name) end end @@ -36,7 +39,7 @@ class Imports::Watcher def file_names(directory_path) Dir.entries(directory_path).select do |file| - ['.gpx', '.json'].include?(File.extname(file)) + SUPPORTED_FORMATS.include?(File.extname(file)) end end @@ -50,8 +53,11 @@ class Imports::Watcher import.raw_data = raw_data(file_path, import.source) import.save! + puts "Import saved for file: #{file_name}" + ImportJob.perform_later(user.id, import.id) + puts "ImportJob enqueued for user_id: #{user.id}, import_id: #{import.id}" end def find_or_initialize_import(user, file_name) @@ -72,9 +78,19 @@ class Imports::Watcher end def source(file_name) - case file_name.split('.').last - when 'json' then :geojson - when 'gpx' then :gpx + case file_name.split('.').last.downcase + 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 else raise UnsupportedSourceError, 'Unsupported source ' end end @@ -82,6 +98,15 @@ class Imports::Watcher def raw_data(file_path, source) file = File.read(file_path) - source.to_sym == :gpx ? Hash.from_xml(file) : JSON.parse(file) + case source.to_sym + when :gpx + Hash.from_xml(file) + when :json, :geojson, :google_phone_takeout, :google_records, :google_semantic_history + JSON.parse(file) + when :owntracks + OwnTracks::RecParser.new(file).call + else + raise UnsupportedSourceError, "Unsupported source: #{source}" + end end -end +end \ No newline at end of file diff --git a/spec/fixtures/files/watched/invalid_user@domain.com/location-history.json b/spec/fixtures/files/watched/invalid_user@domain.com/location-history.json new file mode 100644 index 00000000..88805bc2 --- /dev/null +++ b/spec/fixtures/files/watched/invalid_user@domain.com/location-history.json @@ -0,0 +1,89 @@ +[ + { + "endTime": "2023-08-27T17:04:26.999-05:00", + "startTime": "2023-08-27T15:48:56.000-05:00", + "visit": { + "hierarchyLevel": "0", + "topCandidate": { + "probability": "0.785181", + "semanticType": "Unknown", + "placeID": "ChIJxxP_Qwb2aIYRTwDNDLkUmD0", + "placeLocation": "geo:27.720022,-97.347951" + }, + "probability": "0.710000" + } + }, + { + "endTime": "2023-08-27T22:00:00.000Z", + "startTime": "2023-08-27T20:00:00.000Z", + "timelinePath": [ + { + "point": "geo:27.720007,-97.348044", + "durationMinutesOffsetFromStartTime": "49" + } + ] + }, + { + "endTime": "2023-09-02T23:25:59.000-06:00", + "startTime": "2023-08-27T14:48:56.000-06:00", + "timelineMemory": { + "destinations": [ + { + "identifier": "ChIJs9KSYYBfaIYRj5AOiZNQ0a4" + }, + { + "identifier": "ChIJw6lCfj2sZ4YRl6q2LNNyojk" + }, + { + "identifier": "ChIJA89FstRIAYcRr9I2aBzR89A" + }, + { + "identifier": "ChIJtWVg4r5DFIcRr0zkOeDPEfY" + } + ], + "distanceFromOriginKms": "1594" + } + }, + { + "endTime": "2023-08-28T00:00:00.000Z", + "startTime": "2023-08-27T22:00:00.000Z", + "timelinePath": [ + { + "point": "geo:27.701123,-97.362988", + "durationMinutesOffsetFromStartTime": "4" + }, + { + "point": "geo:27.701123,-97.362988", + "durationMinutesOffsetFromStartTime": "4" + }, + { + "point": "geo:27.687173,-97.363743", + "durationMinutesOffsetFromStartTime": "7" + }, + { + "point": "geo:27.686129,-97.381865", + "durationMinutesOffsetFromStartTime": "10" + }, + { + "point": "geo:27.686129,-97.381865", + "durationMinutesOffsetFromStartTime": "10" + }, + { + "point": "geo:27.686129,-97.381865", + "durationMinutesOffsetFromStartTime": "108" + }, + { + "point": "geo:27.696576,-97.376949", + "durationMinutesOffsetFromStartTime": "109" + }, + { + "point": "geo:27.709617,-97.375988", + "durationMinutesOffsetFromStartTime": "112" + }, + { + "point": "geo:27.709617,-97.375988", + "durationMinutesOffsetFromStartTime": "112" + } + ] + } +] \ No newline at end of file diff --git a/spec/fixtures/files/watched/user@domain.com/2023_January.json b/spec/fixtures/files/watched/user@domain.com/2023_January.json new file mode 100644 index 00000000..1a25ab3c --- /dev/null +++ b/spec/fixtures/files/watched/user@domain.com/2023_January.json @@ -0,0 +1,70 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 14.3439906, + 50.0506312 + ] + }, + "properties": { + "timestamp": "2023-01-01T08:00:00Z" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 14.3439906, + 50.0506312 + ] + }, + "properties": { + "timestamp": "2023-01-01T10:00:00Z" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 14.42076, + 50.08804 + ] + }, + "properties": { + "timestamp": "2023-01-02T12:00:00Z" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 14.42076, + 50.08804 + ] + }, + "properties": { + "timestamp": "2023-01-02T14:00:00Z" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 14.42076, + 50.08804 + ] + }, + "properties": { + "timestamp": "2023-01-02T16:00:00Z" + } + } + ] +} \ No newline at end of file diff --git a/spec/fixtures/files/watched/user@domain.com/Records.json b/spec/fixtures/files/watched/user@domain.com/Records.json new file mode 100644 index 00000000..930ca395 --- /dev/null +++ b/spec/fixtures/files/watched/user@domain.com/Records.json @@ -0,0 +1,40 @@ +{ + "locations": [ + { + "latitudeE7": 533690550, + "longitudeE7": 836950010, + "accuracy": 150, + "source": "UNKNOWN", + "timestamp": "2012-12-15T14:21:29.460Z" + }, + { + "latitudeE7": 533563380, + "longitudeE7": 837616500, + "accuracy": 18000, + "source": "UNKNOWN", + "timestamp": "2013-01-04T10:22:43.225Z" + }, + { + "latitudeE7": 533690589, + "longitudeE7": 836951347, + "accuracy": 22, + "source": "WIFI", + "deviceTag": 1184882232, + "timestamp": "2013-03-01T05:17:39.849Z" + }, + { + "latitudeE7": 533700000, + "longitudeE7": 836960000, + "accuracy": 50, + "source": "GPS", + "timestamp": "2013-04-01T12:00:00.000Z" + }, + { + "latitudeE7": 533710000, + "longitudeE7": 836970000, + "accuracy": 30, + "source": "GPS", + "timestamp": "2013-05-01T08:30:00.000Z" + } + ] +} \ No newline at end of file diff --git a/spec/fixtures/files/watched/user@domain.com/export_same_points.json b/spec/fixtures/files/watched/user@domain.com/export_same_points.json index 2ecfb883..7951ef5a 100644 --- a/spec/fixtures/files/watched/user@domain.com/export_same_points.json +++ b/spec/fixtures/files/watched/user@domain.com/export_same_points.json @@ -1 +1,175 @@ -{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}},{"type":"Feature","geometry":{"type":"Point","coordinates":["37.6173","55.755826"]},"properties":{"battery_status":"unplugged","ping":"MyString","battery":1,"tracker_id":"MyString","topic":"MyString","altitude":1,"longitude":"37.6173","velocity":"0","trigger":"background_event","bssid":"MyString","ssid":"MyString","connection":"wifi","vertical_accuracy":1,"accuracy":1,"timestamp":1609459200,"latitude":"55.755826","mode":1,"inrids":[],"in_regions":[],"city":null,"country":null,"geodata":{}}}]} +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + "37.6173", + "55.755826" + ] + }, + "properties": { + "battery_status": "unplugged", + "ping": "MyString", + "battery": 1, + "tracker_id": "MyString", + "topic": "MyString", + "altitude": 1, + "longitude": "37.6173", + "velocity": "0", + "trigger": "background_event", + "bssid": "MyString", + "ssid": "MyString", + "connection": "wifi", + "vertical_accuracy": 1, + "accuracy": 1, + "timestamp": 1609459200, + "latitude": "55.755826", + "mode": 1, + "inrids": [], + "in_regions": [], + "city": null, + "country": null, + "geodata": {} + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + "37.6173", + "55.755826" + ] + }, + "properties": { + "battery_status": "unplugged", + "ping": "MyString", + "battery": 1, + "tracker_id": "MyString", + "topic": "MyString", + "altitude": 1, + "longitude": "37.6173", + "velocity": "0", + "trigger": "background_event", + "bssid": "MyString", + "ssid": "MyString", + "connection": "wifi", + "vertical_accuracy": 1, + "accuracy": 1, + "timestamp": 1609459200, + "latitude": "55.755826", + "mode": 1, + "inrids": [], + "in_regions": [], + "city": null, + "country": null, + "geodata": {} + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + "37.6173", + "55.755826" + ] + }, + "properties": { + "battery_status": "unplugged", + "ping": "MyString", + "battery": 1, + "tracker_id": "MyString", + "topic": "MyString", + "altitude": 1, + "longitude": "37.6173", + "velocity": "0", + "trigger": "background_event", + "bssid": "MyString", + "ssid": "MyString", + "connection": "wifi", + "vertical_accuracy": 1, + "accuracy": 1, + "timestamp": 1609459200, + "latitude": "55.755826", + "mode": 1, + "inrids": [], + "in_regions": [], + "city": null, + "country": null, + "geodata": {} + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + "37.6173", + "55.755826" + ] + }, + "properties": { + "battery_status": "unplugged", + "ping": "MyString", + "battery": 1, + "tracker_id": "MyString", + "topic": "MyString", + "altitude": 1, + "longitude": "37.6173", + "velocity": "0", + "trigger": "background_event", + "bssid": "MyString", + "ssid": "MyString", + "connection": "wifi", + "vertical_accuracy": 1, + "accuracy": 1, + "timestamp": 1609459200, + "latitude": "55.755826", + "mode": 1, + "inrids": [], + "in_regions": [], + "city": null, + "country": null, + "geodata": {} + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + "37.6173", + "55.755826" + ] + }, + "properties": { + "battery_status": "unplugged", + "ping": "MyString", + "battery": 1, + "tracker_id": "MyString", + "topic": "MyString", + "altitude": 1, + "longitude": "37.6173", + "velocity": "0", + "trigger": "background_event", + "bssid": "MyString", + "ssid": "MyString", + "connection": "wifi", + "vertical_accuracy": 1, + "accuracy": 1, + "timestamp": 1609459200, + "latitude": "55.755826", + "mode": 1, + "inrids": [], + "in_regions": [], + "city": null, + "country": null, + "geodata": {} + } + } + ] +} \ No newline at end of file diff --git a/spec/fixtures/files/watched/user@domain.com/gpx_track_single_segment.gpx b/spec/fixtures/files/watched/user@domain.com/gpx_track_single_segment.gpx index 3176fb4f..7c73a8ac 100644 --- a/spec/fixtures/files/watched/user@domain.com/gpx_track_single_segment.gpx +++ b/spec/fixtures/files/watched/user@domain.com/gpx_track_single_segment.gpx @@ -34,1206 +34,6 @@ 811.41 - - 808.11 - - - - 805.33 - - - - 802.85 - - - - 800.8 - - - - 798.9 - - - - 797.19 - - - - 795.8 - - - - 794.31 - - - - 793.25 - - - - 792.19 - - - - 791.44 - - - - 791.24 - - - - 791.47 - - - - 792.04 - - - - 792.18 - - - - 793.94 - - - - 795.29 - - - - 796.89 - - - - 798.7 - - - - 801.44 - - - - 803.97 - - - - 806.6 - - - - 809.27 - - - - 811.96 - - - - 814.62 - - - - 817.54 - - - - 820.18 - - - - 822.76 - - - - 825.25 - - - - 827.89 - - - - 830.82 - - - - 833.17 - - - - 835.42 - - - - 837.9 - - - - 839.89 - - - - 841.98 - - - - 844.17 - - - - 846.01 - - - - 847.32 - - - - 848.51 - - - - 849.54 - - - - 850.3 - - - - 850.74 - - - - 851.11 - - - - 851.31 - - - - 851.37 - - - - 851.36 - - - - 851.21 - - - - 851.04 - - - - 850.86 - - - - 850.41 - - - - 849.94 - - - - 849.54 - - - - 849.08 - - - - 848.67 - - - - 848.36 - - - - 848.08 - - - - 847.87 - - - - 847.77 - - - - 847.74 - - - - 847.75 - - - - 847.81 - - - - 847.96 - - - - 848.17 - - - - 848.37 - - - - 848.68 - - - - 849.01 - - - - 849.24 - - - - 849.47 - - - - 849.7 - - - - 849.88 - - - - 850.1 - - - - 850.25 - - - - 850.38 - - - - 850.47 - - - - 850.46 - - - - 850.35 - - - - 850.35 - - - - 850.02 - - - - 849.6 - - - - 849.05 - - - - 848.37 - - - - 847.54 - - - - 846.57 - - - - 845.55 - - - - 844.29 - - - - 842.85 - - - - 841.43 - - - - 839.98 - - - - 838.63 - - - - 837.18 - - - - 835.48 - - - - 833.92 - - - - 832.43 - - - - 831.06 - - - - 829.84 - - - - 829.04 - - - - 828.42 - - - - 828.15 - - - - 828.11 - - - - 828.51 - - - - 829.55 - - - - 830.31 - - - - 831.12 - - - - 831.93 - - - - 832.91 - - - - 833.85 - - - - 834.91 - - - - 836.07 - - - - 837.2 - - - - 838.38 - - - - 839.56 - - - - 840.58 - - - - 841.58 - - - - 842.46 - - - - 843.23 - - - - 843.46 - - - - 843.41 - - - - 842.64 - - - - 841.84 - - - - 840.81 - - - - 839.56 - - - - 837.86 - - - - 836.03 - - - - 833.91 - - - - 831.55 - - - - 828.71 - - - - 825.47 - - - - 820.96 - - - - 817.85 - - - - 814.71 - - - - 811.52 - - - - 808.25 - - - - 805.03 - - - - 801.68 - - - - 798.27 - - - - 794.91 - - - - 791.73 - - - - 788.61 - - - - 785.48 - - - - 782.4 - - - - 779.42 - - - - 776.47 - - - - 773.67 - - - - 770.99 - - - - 768.4 - - - - 765.66 - - - - 763.1 - - - - 760.26 - - - - 757.88 - - - - 755.75 - - - - 753.7 - - - - 751.75 - - - - 749.94 - - - - 748.17 - - - - 746.34 - - - - 744.47 - - - - 743.18 - - - - 742.0 - - - - 741.01 - - - - 740.17 - - - - 739.53 - - - - 738.88 - - - - 738.42 - - - - 738.16 - - - - 738.01 - - - - 738.01 - - - - 738.11 - - - - 738.36 - - - - 738.8 - - - - 739.13 - - - - 739.78 - - - - 740.12 - - - - 740.55 - - - - 740.93 - - - - 741.31 - - - - 741.6 - - - - 741.82 - - - - 741.89 - - - - 741.94 - - - - 741.89 - - - - 742.0 - - - - 742.05 - - - - 742.17 - - - - 742.28 - - - - 742.49 - - - - 742.74 - - - - 742.86 - - - - 743.34 - - - - 744.01 - - - - 744.96 - - - - 746.14 - - - - 747.41 - - - - 748.68 - - - - 750.03 - - - - 751.57 - - - - 753.47 - - - - 755.4 - - - - 757.49 - - - - 759.68 - - - - 762.09 - - - - 764.56 - - - - 767.4 - - - - 770.3 - - - - 773.45 - - - - 776.83 - - - - 780.51 - - - - 783.74 - - - - 786.94 - - - - 790.76 - - - - 794.06 - - - - 797.36 - - - - 800.75 - - - - 804.12 - - - - 807.53 - - - - 811.02 - - - - 814.61 - - - - 818.13 - - - - 821.6 - - - - 825.29 - - - - 828.89 - - - - 832.37 - - - - 836.28 - - - - 839.49 - - - - 842.19 - - - - 844.74 - - - - 847.21 - - - - 849.34 - - - - 851.3 - - - - 852.93 - - - - 854.35 - - - - 855.69 - - - - 856.86 - - - - 857.72 - - - - 858.43 - - - - 858.78 - - - - 859.01 - - - - 859.0 - - - - 858.97 - - - - 859.21 - - - - 859.45 - - - - 859.73 - - - - 860.06 - - - - 860.45 - - - - 861.08 - - - - 861.61 - - - - 862.29 - - - - 863.0 - - - - 863.9 - - - - 864.96 - - - - 866.07 - - - - 867.3 - - - - 869.0 - - - - 870.45 - - - - 871.97 - - - - 873.37 - - - - 874.8 - - - - 876.17 - - - - 877.6 - - - - 879.15 - - - - 880.87 - - - - 882.54 - - - - 884.28 - - - - 886.01 - - - - 887.84 - - - - 889.62 - - - - 891.29 - - - - 892.83 - - - - 893.87 - - - - 894.78 - - - - 895.66 - - - - 896.51 - - - - 896.83 - - - - 896.95 - - - - 896.98 - - - - 896.67 - - - - 896.92 - - - - 897.13 - - - - 897.08 - - - - 897.65 - - - - 898.62 - - - - 899.59 - - - - 900.3 - - - - 901.06 - - - - 901.98 - - - - 902.94 - - - - 904.14 - - - - 905.06 - - - - 905.5 - - - - 905.8 - - - - 905.47 - - - - 905.91 - - - - 906.01 - - - - 905.66 - - - - 904.85 - - - - 904.4 - - - - 903.49 - - - - 903.02 - - - - 901.8 - - - - 901.42 - - \ No newline at end of file diff --git a/spec/fixtures/files/watched/user@domain.com/location-history.json b/spec/fixtures/files/watched/user@domain.com/location-history.json new file mode 100644 index 00000000..88805bc2 --- /dev/null +++ b/spec/fixtures/files/watched/user@domain.com/location-history.json @@ -0,0 +1,89 @@ +[ + { + "endTime": "2023-08-27T17:04:26.999-05:00", + "startTime": "2023-08-27T15:48:56.000-05:00", + "visit": { + "hierarchyLevel": "0", + "topCandidate": { + "probability": "0.785181", + "semanticType": "Unknown", + "placeID": "ChIJxxP_Qwb2aIYRTwDNDLkUmD0", + "placeLocation": "geo:27.720022,-97.347951" + }, + "probability": "0.710000" + } + }, + { + "endTime": "2023-08-27T22:00:00.000Z", + "startTime": "2023-08-27T20:00:00.000Z", + "timelinePath": [ + { + "point": "geo:27.720007,-97.348044", + "durationMinutesOffsetFromStartTime": "49" + } + ] + }, + { + "endTime": "2023-09-02T23:25:59.000-06:00", + "startTime": "2023-08-27T14:48:56.000-06:00", + "timelineMemory": { + "destinations": [ + { + "identifier": "ChIJs9KSYYBfaIYRj5AOiZNQ0a4" + }, + { + "identifier": "ChIJw6lCfj2sZ4YRl6q2LNNyojk" + }, + { + "identifier": "ChIJA89FstRIAYcRr9I2aBzR89A" + }, + { + "identifier": "ChIJtWVg4r5DFIcRr0zkOeDPEfY" + } + ], + "distanceFromOriginKms": "1594" + } + }, + { + "endTime": "2023-08-28T00:00:00.000Z", + "startTime": "2023-08-27T22:00:00.000Z", + "timelinePath": [ + { + "point": "geo:27.701123,-97.362988", + "durationMinutesOffsetFromStartTime": "4" + }, + { + "point": "geo:27.701123,-97.362988", + "durationMinutesOffsetFromStartTime": "4" + }, + { + "point": "geo:27.687173,-97.363743", + "durationMinutesOffsetFromStartTime": "7" + }, + { + "point": "geo:27.686129,-97.381865", + "durationMinutesOffsetFromStartTime": "10" + }, + { + "point": "geo:27.686129,-97.381865", + "durationMinutesOffsetFromStartTime": "10" + }, + { + "point": "geo:27.686129,-97.381865", + "durationMinutesOffsetFromStartTime": "108" + }, + { + "point": "geo:27.696576,-97.376949", + "durationMinutesOffsetFromStartTime": "109" + }, + { + "point": "geo:27.709617,-97.375988", + "durationMinutesOffsetFromStartTime": "112" + }, + { + "point": "geo:27.709617,-97.375988", + "durationMinutesOffsetFromStartTime": "112" + } + ] + } +] \ No newline at end of file diff --git a/spec/fixtures/files/watched/user@domain.com/owntracks.rec b/spec/fixtures/files/watched/user@domain.com/owntracks.rec new file mode 100644 index 00000000..473591f7 --- /dev/null +++ b/spec/fixtures/files/watched/user@domain.com/owntracks.rec @@ -0,0 +1,13 @@ +2024-03-01T09:03:09Z * {"bs":2,"p":100.266,"batt":94,"_type":"location","tid":"RO","topic":"owntracks/test/iPhone 12 Pro","alt":36,"lon":13.332,"vel":0,"t":"p","BSSID":"b0:f2:8:45:94:33","SSID":"Home Wifi","conn":"w","vac":4,"acc":10,"tst":1709283789,"lat":52.225,"m":1,"inrids":["5f1d1b"],"inregions":["home"],"_http":true} +2024-03-01T17:46:02Z * {"bs":1,"p":100.28,"batt":94,"_type":"location","tid":"RO","topic":"owntracks/test/iPhone 12 Pro","alt":36,"lon":13.333,"t":"p","vel":0,"BSSID":"b0:f2:8:45:94:33","conn":"w","SSID":"Home Wifi","vac":3,"cog":98,"acc":9,"tst":1709315162,"lat":52.226,"m":1,"inrids":["5f1d1b"],"inregions":["home"],"_http":true} +2024-03-01T18:26:55Z * {"lon":13.334,"acc":5,"wtst":1696359532,"event":"leave","rid":"5f1d1b","desc":"home","topic":"owntracks/test/iPhone 12 Pro/event","lat":52.227,"t":"c","tst":1709317615,"tid":"RO","_type":"transition","_http":true} +2024-03-01T18:26:55Z * {"cog":40,"batt":85,"lon":13.335,"acc":5,"bs":1,"p":100.279,"vel":3,"vac":3,"lat":52.228,"topic":"owntracks/test/iPhone 12 Pro","t":"c","conn":"m","m":1,"tst":1709317615,"alt":36,"_type":"location","tid":"RO","_http":true} +2024-03-01T18:28:30Z * {"cog":38,"batt":85,"lon":13.336,"acc":5,"bs":1,"p":100.349,"vel":3,"vac":3,"lat":52.229,"topic":"owntracks/test/iPhone 12 Pro","t":"v","conn":"m","m":1,"tst":1709317710,"alt":35,"_type":"location","tid":"RO","_http":true} +2024-03-01T18:33:03Z * {"cog":18,"batt":85,"lon":13.337,"acc":5,"bs":1,"p":100.347,"vel":4,"vac":3,"lat":52.230,"topic":"owntracks/test/iPhone 12 Pro","conn":"m","m":1,"tst":1709317983,"alt":36,"_type":"location","tid":"RO","_http":true} +2024-03-01T18:40:11Z * {"cog":43,"batt":85,"lon":13.338,"acc":5,"bs":1,"p":100.348,"vel":6,"vac":3,"lat":52.231,"topic":"owntracks/test/iPhone 12 Pro","conn":"m","m":1,"tst":1709318411,"alt":37,"_type":"location","tid":"RO","_http":true} +2024-03-01T18:42:57Z * {"cog":320,"batt":85,"lon":13.339,"acc":5,"bs":1,"p":100.353,"vel":3,"vac":3,"lat":52.232,"topic":"owntracks/test/iPhone 12 Pro","t":"v","conn":"m","m":1,"tst":1709318577,"alt":37,"_type":"location","tid":"RO","_http":true} +2024-03-01T18:40:08Z lwt {"_type":"lwt","tst":1717459208} +2024-03-01T18:40:09Z waypoints {"_type":"waypoint","desc":"Home","lat":52.232,"lon":13.339,"rad":50,"tst":1717459768} +2024-03-01T18:40:10Z event {"_type":"transition","acc":5,"desc":"Home","event":"enter","lat":52.232,"lon":13.339,"t":"l","tid":"s8","tst":1717460098,"wtst":1717459768} +2024-03-01T18:40:11Z * {"cog":43,"batt":85,"lon":13.338,"acc":5,"bs":1,"p":100.348,"vel":6,"vac":3,"lat":52.231,"topic":"owntracks/test/iPhone 12 Pro","conn":"m","m":1,"tst":1709318411,"alt":37,"_type":"location","tid":"RO","_http":true} +2024-03-01T18:40:11Z * {"cog":43,"batt":85,"lon":13.341,"acc":5,"bs":1,"p":100.348,"created_at":1709318940,"vel":6,"vac":3,"lat":52.234,"topic":"owntracks/test/iPhone 12 Pro","conn":"m","m":1,"tst":1709318411,"alt":37,"_type":"location","tid":"RO","_http":true} diff --git a/spec/services/imports/watcher_spec.rb b/spec/services/imports/watcher_spec.rb index 83dacdf2..65bcd19a 100644 --- a/spec/services/imports/watcher_spec.rb +++ b/spec/services/imports/watcher_spec.rb @@ -11,8 +11,11 @@ RSpec.describe Imports::Watcher do before do stub_const('Imports::Watcher::WATCHED_DIR_PATH', watched_dir_path) + Sidekiq::Testing.inline! end + after { Sidekiq::Testing.fake! } + context 'when there are no files in the watched directory' do it 'does not call ImportJob' do expect(ImportJob).not_to receive(:perform_later) @@ -22,26 +25,34 @@ RSpec.describe Imports::Watcher do end context 'when there are files in the watched directory' do - Sidekiq::Testing.inline! do - context 'when the file has a valid user email' do - it 'creates an import for the user' do - expect { service }.to change(user.imports, :count).by(2) - end + context 'when the file has a valid user email' do + it 'creates an import for the user' do + expect { service }.to change(user.imports, :count).by(6) end - context 'when the file has an invalid user email' do - it 'does not create an import' do - expect { service }.not_to change(Import, :count) - end + it 'creates points for the user' do + initial_point_count = Point.count + service + expect(Point.count).to be > initial_point_count end + end - context 'when the import already exists' do - it 'does not create a new import' do - create(:import, user:, name: 'export_same_points.json') - create(:import, user:, name: 'gpx_track_single_segment.gpx') + context 'when the file has an invalid user email' do + it 'does not create an import' do + expect { service }.not_to change(Import, :count) + end + end - expect { service }.not_to change(Import, :count) - end + context 'when the import already exists' do + it 'does not create a new import' do + create(:import, user:, name: '2023_January.json') + create(:import, user:, name: 'export_same_points.json') + create(:import, user:, name: 'gpx_track_single_segment.gpx') + create(:import, user:, name: 'location-history.json') + create(:import, user:, name: 'owntracks.rec') + create(:import, user:, name: 'Records.json') + + expect { service }.not_to change(Import, :count) end end end