open Cmdliner (** List people command *) let list_people env _xdg profile base_url limit hidden = Eio.Switch.run @@ fun sw -> let api_key = Keyeio.Profile.get_required profile ~key:"api_key" in let base_url = match base_url with | Some url -> url | None -> Keyeio.Profile.get profile ~key:"base_url" |> Option.value ~default:"https://photos.example.com" in try let requests_session = Requests.create ~sw env in let client = Immich.create ~requests_session ~base_url ~api_key in let response = Immich.fetch_people client in (* Filter by hidden status if requested *) let people = List.filter (fun (p : Immich.person) -> match hidden with | Some true -> p.is_hidden | Some false -> not p.is_hidden | None -> true ) response.people in (* Limit number of results *) let people = match limit with | Some n -> List.filteri (fun i _ -> i < n) people | None -> people in Printf.printf "Found %d people (total: %d, visible: %d)\n\n" (List.length people) response.total response.visible; List.iteri (fun i (p : Immich.person) -> Printf.printf "%d. %s\n" (i + 1) p.name; Printf.printf " ID: %s\n" p.id; (match p.birth_date with | Some bd -> Printf.printf " Birth date: %s\n" bd | None -> ()); Printf.printf " Thumbnail: %s\n" p.thumbnail_path; if p.is_hidden then Printf.printf " [HIDDEN]\n"; Printf.printf "\n" ) people; 0 with exn -> Printf.eprintf "Error: %s\n" (Printexc.to_string exn); 1 (** Get a single person by ID *) let get_person env _xdg profile base_url person_id = Eio.Switch.run @@ fun sw -> let api_key = Keyeio.Profile.get_required profile ~key:"api_key" in let base_url = match base_url with | Some url -> url | None -> Keyeio.Profile.get profile ~key:"base_url" |> Option.value ~default:"https://photos.example.com" in try let requests_session = Requests.create ~sw env in let client = Immich.create ~requests_session ~base_url ~api_key in let person = Immich.fetch_person client ~person_id in Printf.printf "Person: %s\n" person.name; Printf.printf "ID: %s\n" person.id; (match person.birth_date with | Some bd -> Printf.printf "Birth date: %s\n" bd | None -> ()); Printf.printf "Thumbnail: %s\n" person.thumbnail_path; if person.is_hidden then Printf.printf "Status: HIDDEN\n"; 0 with exn -> Printf.eprintf "Error: %s\n" (Printexc.to_string exn); 1 (** Search for people by name *) let search_people env _xdg profile base_url name = Eio.Switch.run @@ fun sw -> let api_key = Keyeio.Profile.get_required profile ~key:"api_key" in let base_url = match base_url with | Some url -> url | None -> Keyeio.Profile.get profile ~key:"base_url" |> Option.value ~default:"https://photos.example.com" in try let requests_session = Requests.create ~sw env in let client = Immich.create ~requests_session ~base_url ~api_key in let people = Immich.search_person client ~name in Printf.printf "Found %d people matching '%s'\n\n" (List.length people) name; List.iteri (fun i (p : Immich.person) -> Printf.printf "%d. %s\n" (i + 1) p.name; Printf.printf " ID: %s\n" p.id; (match p.birth_date with | Some bd -> Printf.printf " Birth date: %s\n" bd | None -> ()); Printf.printf " Thumbnail: %s\n" p.thumbnail_path; if p.is_hidden then Printf.printf " [HIDDEN]\n"; Printf.printf "\n" ) people; 0 with exn -> Printf.eprintf "Error: %s\n" (Printexc.to_string exn); 1 (** Command-line arguments *) let base_url_arg = let doc = "Base URL of the Immich instance (overrides profile setting)" in Arg.(value & opt (some string) None & info ["u"; "url"] ~docv:"URL" ~doc) let limit_arg = let doc = "Maximum number of results to return" in Arg.(value & opt (some int) None & info ["l"; "limit"] ~docv:"N" ~doc) let hidden_arg = let doc = "Filter by hidden status (true/false)" in Arg.(value & opt (some bool) None & info ["hidden"] ~docv:"BOOL" ~doc) let person_id_arg = let doc = "ID of the person" in Arg.(required & pos 0 (some string) None & info [] ~docv:"PERSON_ID" ~doc) let name_arg = let doc = "Name to search for" in Arg.(required & pos 0 (some string) None & info [] ~docv:"NAME" ~doc) (** Commands *) let list_cmd = let doc = "List people from Immich" in Eiocmd.run ~info:(Cmd.info "list" ~doc) ~app_name:"immich" ~service:"immich" Term.(const (fun base_url limit hidden env xdg profile -> list_people env xdg profile base_url limit hidden) $ base_url_arg $ limit_arg $ hidden_arg) let get_cmd = let doc = "Get a person by ID" in Eiocmd.run ~info:(Cmd.info "get" ~doc) ~app_name:"immich" ~service:"immich" Term.(const (fun base_url person_id env xdg profile -> get_person env xdg profile base_url person_id) $ base_url_arg $ person_id_arg) let search_cmd = let doc = "Search for people by name" in Eiocmd.run ~info:(Cmd.info "search" ~doc) ~app_name:"immich" ~service:"immich" Term.(const (fun base_url name env xdg profile -> search_people env xdg profile base_url name) $ base_url_arg $ name_arg) (** Main command *) let main_cmd = let doc = "Immich API client" in let man = [ `S Manpage.s_description; `P "$(tname) is a command-line client for the Immich API."; `P "It allows you to list, search, and view people from your Immich instance."; ] in let info = Cmd.info "immich" ~version:"0.1.0" ~doc ~man in Cmd.group info [list_cmd; get_cmd; search_cmd] let () = exit (Cmd.eval' main_cmd)