Add basic Photoprism photos integration

This commit is contained in:
Eugene Burmakin 2024-12-02 16:52:05 +01:00
parent f94ea5516e
commit 1f9e1f2f97
6 changed files with 105 additions and 13 deletions

View file

@ -12,16 +12,11 @@ class Api::V1::SettingsController < ApiController
settings_params.each { |key, value| current_api_user.settings[key] = value }
if current_api_user.save
render json: {
message: 'Settings updated',
settings: current_api_user.settings,
status: 'success'
}, status: :ok
render json: { message: 'Settings updated', settings: current_api_user.settings, status: 'success' },
status: :ok
else
render json: {
message: 'Something went wrong',
errors: current_api_user.errors.full_messages
}, status: :unprocessable_entity
render json: { message: 'Something went wrong', errors: current_api_user.errors.full_messages },
status: :unprocessable_entity
end
end
@ -31,7 +26,8 @@ class Api::V1::SettingsController < ApiController
params.require(:settings).permit(
:meters_between_routes, :minutes_between_routes, :fog_of_war_meters,
:time_threshold_minutes, :merge_threshold_minutes, :route_opacity,
:preferred_map_layer, :points_rendering_mode, :live_map_enabled
:preferred_map_layer, :points_rendering_mode, :live_map_enabled,
:immich_url, :immich_api_key, :photoprism_url, :photoprism_api_key
)
end
end

View file

@ -31,7 +31,7 @@ class SettingsController < ApplicationController
params.require(:settings).permit(
:meters_between_routes, :minutes_between_routes, :fog_of_war_meters,
:time_threshold_minutes, :merge_threshold_minutes, :route_opacity,
:immich_url, :immich_api_key
:immich_url, :immich_api_key, :photoprism_url, :photoprism_api_key
)
end
end

View file

@ -18,6 +18,7 @@ class User < ApplicationRecord
has_many :trips, dependent: :destroy
after_create :create_api_key
before_save :strip_trailing_slashes
def countries_visited
stats.pluck(:toponyms).flatten.map { _1['country'] }.uniq.compact
@ -60,4 +61,9 @@ class User < ApplicationRecord
save
end
def strip_trailing_slashes
settings['immich_url'].gsub!(%r{/+\z}, '')
settings['photoprism_url'].gsub!(%r{/+\z}, '')
end
end

View file

@ -0,0 +1,80 @@
# frozen_string_literal: true
class Photoprism::RequestPhotos
attr_reader :user, :photoprism_api_base_url, :photoprism_api_key, :start_date, :end_date
def initialize(user, start_date: '1970-01-01', end_date: nil)
@user = user
@photoprism_api_base_url = "#{user.settings['photoprism_url']}/api/v1/photos"
@photoprism_api_key = user.settings['photoprism_api_key']
@start_date = start_date
@end_date = end_date
end
def call
raise ArgumentError, 'Photoprism API key is missing' if photoprism_api_key.blank?
raise ArgumentError, 'Photoprism URL is missing' if user.settings['photoprism_url'].blank?
data = retrieve_photoprism_data
time_framed_data(data)
end
private
def retrieve_photoprism_data
data = []
offset = 0
while offset < 1_000_000
response = HTTParty.get(
photoprism_api_base_url,
headers: headers,
query: request_params(offset)
)
break if response.code != 200
photoprism_data = JSON.parse(response.body)
data << photoprism_data
break if photoprism_data.empty?
offset += 1000
end
data
end
def headers
{
'Authorization' => "Bearer #{photoprism_api_key}",
'accept' => 'application/json'
}
end
def request_params(offset = 0)
params = {
q: '',
public: true,
quality: 3,
after: start_date,
offset: offset,
count: 1000
}
params.delete(:offset) if offset.zero?
params[:before] = end_date if end_date.present?
params
end
def time_framed_data(data)
data.flatten.select do |photo|
taken_at = DateTime.parse(photo['TakenAtLocal'])
end_date ||= Time.current
taken_at.between?(start_date.to_datetime, end_date.to_datetime)
end
end
end

View file

@ -1,5 +1,5 @@
<div role="tablist" class="tabs tabs-lifted tabs-lg">
<%= link_to 'Main', settings_path, role: 'tab', class: "tab #{active_tab?(settings_path)}" %>
<%= link_to 'Integrations', settings_path, role: 'tab', class: "tab #{active_tab?(settings_path)}" %>
<% if current_user.admin? %>
<%= link_to 'Users', settings_users_path, role: 'tab', class: "tab #{active_tab?(settings_users_path)}" %>
<%= link_to 'Background Jobs', settings_background_jobs_path, role: 'tab', class: "tab #{active_tab?(settings_background_jobs_path)}" %>

View file

@ -5,7 +5,7 @@
<div class="flex flex-col lg:flex-row w-full my-10 space-x-4">
<div class="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100 px-5 py-5 mx-5">
<h2 class="text-2xl font-bold">Edit your Dawarich settings!</h1>
<h2 class="text-2xl font-bold">Edit your Integrations settings!</h1>
<%= form_for :settings, url: settings_path, method: :patch, data: { turbo_method: :patch, turbo: false } do |f| %>
<div class="form-control my-2">
<%= f.label :immich_url %>
@ -15,6 +15,16 @@
<%= f.label :immich_api_key %>
<%= f.text_field :immich_api_key, value: current_user.settings['immich_api_key'], class: "input input-bordered", placeholder: 'xxxxxxxxxxxxxx' %>
</div>
<div class="divider"></div>
<div class="form-control my-2">
<%= f.label :photoprism_url %>
<%= f.text_field :photoprism_url, value: current_user.settings['photoprism_url'], class: "input input-bordered", placeholder: 'http://192.168.0.1:2342' %>
</div>
<div class="form-control my-2">
<%= f.label :photoprism_api_key %>
<%= f.text_field :photoprism_api_key, value: current_user.settings['photoprism_api_key'], class: "input input-bordered", placeholder: 'xxxxxxxxxxxxxx' %>
</div>
<div class="form-control my-2">
<%= f.submit "Update", class: "btn btn-primary" %>
</div>