mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 01:31:39 -05:00
Add a button to import Photoprism geodata
This commit is contained in:
parent
42b74ecd52
commit
e17b671c9c
7 changed files with 116 additions and 7 deletions
|
|
@ -7,6 +7,8 @@ class EnqueueBackgroundJob < ApplicationJob
|
||||||
case job_name
|
case job_name
|
||||||
when 'start_immich_import'
|
when 'start_immich_import'
|
||||||
Import::ImmichGeodataJob.perform_later(user_id)
|
Import::ImmichGeodataJob.perform_later(user_id)
|
||||||
|
when 'start_photoprism_import'
|
||||||
|
Import::PhotoprismGeodataJob.perform_later(user_id)
|
||||||
when 'start_reverse_geocoding', 'continue_reverse_geocoding'
|
when 'start_reverse_geocoding', 'continue_reverse_geocoding'
|
||||||
Jobs::Create.new(job_name, user_id).call
|
Jobs::Create.new(job_name, user_id).call
|
||||||
else
|
else
|
||||||
|
|
|
||||||
12
app/jobs/import/photoprism_geodata_job.rb
Normal file
12
app/jobs/import/photoprism_geodata_job.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Import::PhotoprismGeodataJob < ApplicationJob
|
||||||
|
queue_as :imports
|
||||||
|
sidekiq_options retry: false
|
||||||
|
|
||||||
|
def perform(user_id)
|
||||||
|
user = User.find(user_id)
|
||||||
|
|
||||||
|
Photoprism::ImportGeodata.new(user).call
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -10,7 +10,7 @@ class Import < ApplicationRecord
|
||||||
|
|
||||||
enum :source, {
|
enum :source, {
|
||||||
google_semantic_history: 0, owntracks: 1, google_records: 2,
|
google_semantic_history: 0, owntracks: 1, google_records: 2,
|
||||||
google_phone_takeout: 3, gpx: 4, immich_api: 5, geojson: 6
|
google_phone_takeout: 3, gpx: 4, immich_api: 5, geojson: 6, photoprism_api: 7
|
||||||
}
|
}
|
||||||
|
|
||||||
def process!
|
def process!
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class Immich::ImportGeodata
|
||||||
end
|
end
|
||||||
|
|
||||||
def log_no_data
|
def log_no_data
|
||||||
Rails.logger.info 'No data found'
|
Rails.logger.info 'No geodata found for Immich'
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_import_failed_notification(import_name)
|
def create_import_failed_notification(import_name)
|
||||||
|
|
|
||||||
80
app/services/photoprism/import_geodata.rb
Normal file
80
app/services/photoprism/import_geodata.rb
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Photoprism::ImportGeodata
|
||||||
|
attr_reader :user, :start_date, :end_date
|
||||||
|
|
||||||
|
def initialize(user, start_date: '1970-01-01', end_date: nil)
|
||||||
|
@user = user
|
||||||
|
@start_date = start_date
|
||||||
|
@end_date = end_date
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
photoprism_data = retrieve_photoprism_data
|
||||||
|
|
||||||
|
log_no_data and return if photoprism_data.empty?
|
||||||
|
|
||||||
|
photoprism_data_json = parse_photoprism_data(photoprism_data)
|
||||||
|
file_name = file_name(photoprism_data_json)
|
||||||
|
import = user.imports.find_or_initialize_by(name: file_name, source: :photoprism_api)
|
||||||
|
|
||||||
|
create_import_failed_notification(import.name) and return unless import.new_record?
|
||||||
|
|
||||||
|
import.raw_data = photoprism_data_json
|
||||||
|
import.save!
|
||||||
|
|
||||||
|
ImportJob.perform_later(user.id, import.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def retrieve_photoprism_data
|
||||||
|
Photoprism::RequestPhotos.new(user, start_date:, end_date:).call
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_photoprism_data(photoprism_data)
|
||||||
|
geodata = photoprism_data.map do |asset|
|
||||||
|
next unless valid?(asset)
|
||||||
|
|
||||||
|
extract_geodata(asset)
|
||||||
|
end
|
||||||
|
|
||||||
|
geodata.compact.sort_by { |data| data[:timestamp] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid?(asset)
|
||||||
|
asset['Lat'] &&
|
||||||
|
asset['Lat'] != 0 &&
|
||||||
|
asset['Lng'] &&
|
||||||
|
asset['Lng'] != 0 &&
|
||||||
|
asset['TakenAt']
|
||||||
|
end
|
||||||
|
|
||||||
|
def extract_geodata(asset)
|
||||||
|
{
|
||||||
|
latitude: asset.dig('exifInfo', 'latitude'),
|
||||||
|
longitude: asset.dig('exifInfo', 'longitude'),
|
||||||
|
timestamp: Time.zone.parse(asset.dig('exifInfo', 'dateTimeOriginal')).to_i
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_no_data
|
||||||
|
Rails.logger.info 'No geodata found for Photoprism'
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_import_failed_notification(import_name)
|
||||||
|
Notifications::Create.new(
|
||||||
|
user:,
|
||||||
|
kind: :info,
|
||||||
|
title: 'Import was not created',
|
||||||
|
content: "Import with the same name (#{import_name}) already exists. If you want to proceed, delete the existing import and try again."
|
||||||
|
).call
|
||||||
|
end
|
||||||
|
|
||||||
|
def file_name(photoprism_data_json)
|
||||||
|
from = Time.zone.at(photoprism_data_json.first[:timestamp]).to_date
|
||||||
|
to = Time.zone.at(photoprism_data_json.last[:timestamp]).to_date
|
||||||
|
|
||||||
|
"photoprism-geodata-#{user.email}-from-#{from}-to-#{to}.json"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -10,6 +10,11 @@
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href='' class="rounded-lg py-3 px-5 bg-blue-900 text-gray block font-medium tooltip cursor-not-allowed" data-tip="You need to provide your Immich instance data in the Settings">Import Immich data</a>
|
<a href='' class="rounded-lg py-3 px-5 bg-blue-900 text-gray block font-medium tooltip cursor-not-allowed" data-tip="You need to provide your Immich instance data in the Settings">Import Immich data</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% if current_user.settings['photoprism_url'] && current_user.settings['photoprism_api_key'] %>
|
||||||
|
<%= link_to 'Import Photoprism data', settings_background_jobs_path(job_name: 'start_photoprism_import'), method: :post, data: { confirm: 'Are you sure?', turbo_confirm: 'Are you sure?', turbo_method: :post }, class: 'rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium' %>
|
||||||
|
<% else %>
|
||||||
|
<a href='' class="rounded-lg py-3 px-5 bg-blue-900 text-gray block font-medium tooltip cursor-not-allowed" data-tip="You need to provide your Photoprism instance data in the Settings">Import Photoprism data</a>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="imports" class="min-w-full">
|
<div id="imports" class="min-w-full">
|
||||||
|
|
|
||||||
|
|
@ -9,25 +9,35 @@ RSpec.describe 'Api::V1::Photos', type: :request do
|
||||||
let(:photo_data) do
|
let(:photo_data) do
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
'id' => '123',
|
'id' => 1,
|
||||||
'latitude' => 35.6762,
|
'latitude' => 35.6762,
|
||||||
'longitude' => 139.6503,
|
'longitude' => 139.6503,
|
||||||
'localDateTime' => '2024-01-01T00:00:00.000Z',
|
'localDateTime' => '2024-01-01T00:00:00.000Z',
|
||||||
'type' => 'photo'
|
'originalFileName' => 'photo1.jpg',
|
||||||
|
'city' => 'Tokyo',
|
||||||
|
'state' => 'Tokyo',
|
||||||
|
'country' => 'Japan',
|
||||||
|
'type' => 'photo',
|
||||||
|
'source' => 'photoprism'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id' => '456',
|
'id' => 2,
|
||||||
'latitude' => 40.7128,
|
'latitude' => 40.7128,
|
||||||
'longitude' => -74.0060,
|
'longitude' => -74.0060,
|
||||||
'localDateTime' => '2024-01-02T00:00:00.000Z',
|
'localDateTime' => '2024-01-02T00:00:00.000Z',
|
||||||
'type' => 'photo'
|
'originalFileName' => 'photo2.jpg',
|
||||||
|
'city' => 'New York',
|
||||||
|
'state' => 'New York',
|
||||||
|
'country' => 'USA',
|
||||||
|
'type' => 'photo',
|
||||||
|
'source' => 'immich'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the request is successful' do
|
context 'when the request is successful' do
|
||||||
before do
|
before do
|
||||||
allow_any_instance_of(Immich::RequestPhotos).to receive(:call).and_return(photo_data)
|
allow_any_instance_of(Photos::Request).to receive(:call).and_return(photo_data)
|
||||||
|
|
||||||
get '/api/v1/photos', params: { api_key: user.api_key }
|
get '/api/v1/photos', params: { api_key: user.api_key }
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue