diff --git a/.gitignore b/.gitignore index 14295128..3e2a87f6 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,5 @@ /config/credentials/production.key /config/credentials/production.yml.enc + +Makefile diff --git a/CHANGELOG.md b/CHANGELOG.md index c8bda809..8c9d9b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -# 0.25.5 - UNRELEASED +# 0.25.5 - 2025-04-13 ## Removed - Optional telemetry was removed from the app. - Sidekiq Web UI is now protected by basic auth in non-self-hosted mode. (Needs to be tested) +## Changed + +- `rake points:migrate_to_lonlat` task now also tries to extract latitude and longitude from `raw_data` column before using `longitude` and `latitude` columns to fill `lonlat` column. + # 0.25.4 - 2025-04-02 diff --git a/Makefile b/Makefile deleted file mode 100644 index e69de29b..00000000 diff --git a/app/services/photos/import_parser.rb b/app/services/photos/import_parser.rb index b91a9ca3..fec7bba8 100644 --- a/app/services/photos/import_parser.rb +++ b/app/services/photos/import_parser.rb @@ -3,16 +3,19 @@ class Photos::ImportParser include Imports::Broadcaster include PointValidation - attr_reader :import, :json, :user_id + attr_reader :import, :user_id def initialize(import, user_id) @import = import - @json = import.raw_data @user_id = user_id end def call - json.each.with_index(1) { |point, index| create_point(point, index) } + import.file.download do |file| + json = Oj.load(file) + + json.each.with_index(1) { |point, index| create_point(point, index) } + end end def create_point(point, index) diff --git a/app/services/points/raw_data_lonlat_extractor.rb b/app/services/points/raw_data_lonlat_extractor.rb new file mode 100644 index 00000000..81071976 --- /dev/null +++ b/app/services/points/raw_data_lonlat_extractor.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class Points::RawDataLonlatExtractor + def initialize(point) + @point = point + end + + def call + lonlat = extract_lonlat(@point) + + @point.update( + longitude: lonlat[0], + latitude: lonlat[1] + ) + end + + private + + # rubocop:disable Metrics/MethodLength + def extract_lonlat(point) + if point.raw_data['activitySegment']['waypointPath']['waypoints'][0] + # google_semantic_history_parser + [ + point.raw_data['activitySegment']['waypointPath']['waypoints'][0]['lngE7'].to_f / 10**7, + point.raw_data['activitySegment']['waypointPath']['waypoints'][0]['latE7'].to_f / 10**7 + ] + elsif point.raw_data['longitudeE7'] && point.raw_data['latitudeE7'] + # google records + [ + point.raw_data['longitudeE7'].to_f / 10**7, + point.raw_data['latitudeE7'].to_f / 10**7 + ] + elsif point.raw_data['position']['LatLng'] + # google phone export + raw_coordinates = point.raw_data['position']['LatLng'] + if raw_coordinates.include?('°') + raw_coordinates.split(', ').map { _1.chomp('°') } + else + raw_coordinates.delete('geo:').split(',') + end + elsif point.raw_data['lon'] && point.raw_data['lat'] + # gpx_track_importer, owntracks + [point.raw_data['lon'], point.raw_data['lat']] + elsif point.raw_data['geometry']['coordinates'][0] && point.raw_data['geometry']['coordinates'][1] + # geojson + [ + point.raw_data['geometry']['coordinates'][0], + point.raw_data['geometry']['coordinates'][1] + ] + elsif point.raw_data['longitude'] && point.raw_data['latitude'] + # immich_api, photoprism_api + [point.raw_data['longitude'], point.raw_data['latitude']] + end + end + # rubocop:enable Metrics/MethodLength +end diff --git a/app/views/shared/_navbar.html.erb b/app/views/shared/_navbar.html.erb index 802bc92b..085cbd74 100644 --- a/app/views/shared/_navbar.html.erb +++ b/app/views/shared/_navbar.html.erb @@ -98,8 +98,8 @@