Closed photomatix18 closed 2 months ago
I was thinking this exact thing earlier today! Get out of my mind! :D
It's not possible at the moment. I think it would require substantial changes to how the config works to implement this. Though I do see the benefit.
Good point. You'd have to either split up the config into multiple files (sort of like how nginx does? config1.yaml
, config2.yaml
, ...?), maybe with one "main" config with all the regular settings and then an additional file for each api_key or you'd have to start doing more indenting and making the yaml confugly (I really dislike yaml!).
Good point. You'd have to either split up the config into multiple files (sort of like how nginx does?
config1.yaml
,config2.yaml
, ...?), maybe with one "main" config with all the regular settings and then an additional file for each api_key or you'd have to start doing more indenting and making the yaml confugly (I really dislike yaml!).
I used to really dislike yaml but it's much better then JSON for configs imo. I'm also quite fond of TOML.
multiple configs sounds interesting or maybe "profiles".
then use:
http://{KIOSK_URL}?profile=1
or http://{KIOSK_URL}?profile=CUSTOM_NAME
with a possible:
http://{KIOSK_URL}?profile=random
but it raises the issue of album/people params in the url 😵💫
Not my baby but I think I'd avoid that :) If someone really wants profiles they can spin up another version on a different port. That's getting too far into the weeds imho
Not my baby but I think I'd avoid that :) If someone really wants profiles they can spin up another version on a different port. That's getting too far into the weeds imho
I am inclined to agree.
Really in the end, if Immich gets the "smart" albums working, that would solve the issue.
Yup and it’s one of the most requested features so I assume it will be implemented sooner rather then later. On 14 Sep 2024 at 4:47 PM +0100, photomatix18 @.***>, wrote:
Really in the end, if Immich gets the "smart" albums working, that would solve the issue. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>
My solution to this problem is a shared album between my wife and I and a python script that runs on a cron schedule. The script takes our API keys, the people IDs of our son, and a destination album id and then it simply queries the previous days worth of assets for each given API:person pair and adds them to the album.
And then kiosk just points at this album only.
#!/usr/bin/python3
import logging
import json
import argparse
import requests
from datetime import datetime, timedelta, timezone
def __const_modifier_options():
return "hdw"
def get_calculated_date(shorthand):
import re
shorthand = str(shorthand)
pattern=r'^(?P<integer>[0-9]{1,})(?P<modifier>['+f'{__const_modifier_options()}'+r'])$'
re_pattern=re.compile(pattern, re.IGNORECASE)
try:
assert(re_pattern.match(shorthand)),f'{shorthand} failed to pass validation'
match_dict = re_pattern.search(shorthand).groupdict()
integer = int(match_dict["integer"])
modifier = match_dict["modifier"]
now = datetime.now(timezone.utc)
match modifier.lower():
case "h":
return now - timedelta(hours=integer)
case "d":
return now - timedelta(days=integer)
case "w":
return now - timedelta(weeks=integer)
''' case "m":
return now - timedelta(months=integer)
case "y":
return now - timedelta(years=integer)''' # unsupported
except AssertionError as e:
print(e)
exit(1)
def get_headers(api_key):
return { "Content-Type": "application/json", "accept" : "application/json", "x-api-key": api_key }
def get_timeline_buckets(host, api_key, params):
url = f'api/timeline/buckets'
uri = f'http://{host}/{url}'
headers = get_headers(api_key)
response = requests.get(uri, params=params, headers=headers)
return response.json()
def get_timeline_bucket(host, api_key, params):
url = f'api/timeline/bucket'
uri = f'http://{host}/{url}'
headers = get_headers(api_key)
response = requests.get(uri, params=params, headers=headers)
return response.json()
def add_assets_to_album(host, api_key, destination, assets):
url = f'api/albums/{destination}/assets'
uri = f'http://{host}/{url}'
headers = get_headers(api_key)
payload = json.dumps({"ids" : assets})
response = requests.request("PUT", uri, headers=headers, data=payload)
return
def get_assets_for_person(host, api_key, person_uid, date_from=None):
params = {"isArchived":"false","personId":person_uid,"size":"MONTH"}
if date_from: # there's only DAY and MONTH available
if date_from >= (datetime.now(timezone.utc) - timedelta(days=31)):
params["size"] = "DAY"
asset_ids = []
buckets = get_timeline_buckets(host, api_key, params)
for bucket in buckets:
if date_from:
if datetime.strptime(bucket["timeBucket"], "%Y-%m-%dT%H:%M:%S.%f%z") < date_from: break
params["timeBucket"] = bucket["timeBucket"]
bucket = get_timeline_bucket(host, api_key, params)
asset_ids += [ asset["id"] for asset in bucket ]
return asset_ids
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
parser = argparse.ArgumentParser()
parser.add_argument("-i","--immich-host"
,help="Input -h 127.0.0.1:2283 or wherever your instance is hosted"
,required=True
)
parser.add_argument("-p","--person"
,action="append"
,nargs=2
,metavar=("api_key","person_uid")
,help="Input -p api_key person_uid for each account you want to merge into an album"
,required=True
)
parser.add_argument("-d","--destination"
,required=True
,help="Input -d album_uid to set the destination where assets are to be added to. This album has to be shared to all members that this script executes as."
)
parser.add_argument("-df","--date-from"
,required=False
,help="Input a shorthand format to get assets from a calculated timeframe. Not including this option means that all assets from all time will be obtained. The accepted shorthand format is <integer><modifier> where modifier can be [h(our)/d(ay)/w(eek)]. I.e. 7d means 7 days ago. 3h means 3 hours ago."
)
args = parser.parse_args()
host = args.immich_host
dest = args.destination
date = get_calculated_date(args.date_from) if args.date_from else None
for set in args.person:
api_key, puid = (set[0], set[1])
assets = get_assets_for_person(host, api_key, puid, date_from=date)
print(f"adding {len(assets)} assets to the destination album")
add_assets_to_album(host, api_key, dest, assets)
Nice and resourceful! I did see another Python script that was similar to this. It utilised the searchMetaData api endpoint so I was investigating how they used it. On 15 Sep 2024 at 12:10 PM +0100, lobs323 @.***>, wrote:
My solution to this problem is a shared album between my wife and I and a python script that runs on a cron schedule. The script takes our API keys, the people IDs of our son, and a destination album id and then it simply queries the previous days worth of assets for each given API:person pair and adds them to the album. And then kiosk just points at this album only.
!/usr/bin/python3
import logging import json import argparse import requests from datetime import datetime, timedelta, timezone
def __const_modifier_options(): return "hdw"
def get_calculated_date(shorthand): import re shorthand = str(shorthand) pattern=r'^(?P
[0-9]{1,})(?P ['+f'{__const_modifier_options()}'+r'])$' re_pattern=re.compile(pattern, re.IGNORECASE) try: assert(re_pattern.match(shorthand)),f'{shorthand} failed to pass validation' match_dict = re_pattern.search(shorthand).groupdict() integer = int(match_dict["integer"]) modifier = match_dict["modifier"] now = datetime.now(timezone.utc) match modifier.lower(): case "h": return now - timedelta(hours=integer) case "d": return now - timedelta(days=integer) case "w": return now - timedelta(weeks=integer) ''' case "m": return now - timedelta(months=integer) case "y": return now - timedelta(years=integer)''' # unsupported except AssertionError as e: print(e) exit(1) def get_headers(api_key): return { "Content-Type": "application/json", "accept" : "application/json", "x-api-key": api_key }
def get_timeline_buckets(host, api_key, params): url = f'api/timeline/buckets' uri = f'http://{host}/{url}' headers = get_headers(api_key) response = requests.get(uri, params=params, headers=headers) return response.json()
def get_timeline_bucket(host, api_key, params): url = f'api/timeline/bucket' uri = f'http://{host}/{url}' headers = get_headers(api_key) response = requests.get(uri, params=params, headers=headers) return response.json()
def add_assets_to_album(host, api_key, destination, assets): url = f'api/albums/{destination}/assets' uri = f'http://{host}/{url}' headers = get_headers(api_key) payload = json.dumps({"ids" : assets}) response = requests.request("PUT", uri, headers=headers, data=payload) return
def get_assets_for_person(host, api_key, person_uid, date_from=None): params = {"isArchived":"false","personId":person_uid,"size":"MONTH"} if date_from: # there's only DAY and MONTH available if date_from >= (datetime.now(timezone.utc) - timedelta(days=31)): params["size"] = "DAY" asset_ids = [] buckets = get_timeline_buckets(host, api_key, params) for bucket in buckets: if date_from: if datetime.strptime(bucket["timeBucket"], "%Y-%m-%dT%H:%M:%S.%f%z") < date_from: break params["timeBucket"] = bucket["timeBucket"] bucket = get_timeline_bucket(host, api_key, params) asset_ids += [ asset["id"] for asset in bucket ] return asset_ids
if name == "main": logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger() logger.setLevel(logging.DEBUG)
parser = argparse.ArgumentParser() parser.add_argument("-i","--immich-host" ,help="Input -h 127.0.0.1:2283 or wherever your instance is hosted" ,required=True ) parser.add_argument("-p","--person" ,action="append" ,nargs=2 ,metavar=("api_key","person_uid") ,help="Input -p api_key person_uid for each account you want to merge into an album" ,required=True ) parser.add_argument("-d","--destination" ,required=True ,help="Input -d album_uid to set the destination where assets are to be added to. This album has to be shared to all members that this script executes as." ) parser.add_argument("-df","--date-from" ,required=False ,help="Input a shorthand format to get assets from a calculated timeframe. Not including this option means that all assets from all time will be obtained. The accepted shorthand format is <integer><modifier> where modifier can be [h(our)/d(ay)/w(eek)]. I.e. 7d means 7 days ago. 3h means 3 hours ago." ) args = parser.parse_args() host = args.immich_host dest = args.destination date = get_calculated_date(args.date_from) if args.date_from else None for set in args.person: api_key, puid = (set[0], set[1]) assets = get_assets_for_person(host, api_key, puid, date_from=date) print(f"adding {len(assets)} assets to the destination album") add_assets_to_album(host, api_key, dest, assets)
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you modified the open/close state.Message ID: @.***>
This may already be possible and I just missed it in the documentation, but is there a way to specify multiple accounts/api's and specify people for each account to pull from both accounts simultaneously? i.g. I would like to show pictures from both my wife's timeline and mine but only of us and our children.
I'm assuming you could do this with a shared album, but "smart" albums aren't a thing yet, correct? So it would have to be manually updated.