My agentic slop goes here. Not intended for anyone else!
1(** Immiche - Immich API client library *)
2
3open Printf
4
5(** {1 Types} *)
6
7type 'net t_internal = {
8 base_url: string;
9 api_key: string;
10 requests_session: (float Eio.Time.clock_ty Eio.Resource.t, 'net Eio.Net.ty Eio.Resource.t) Requests.t;
11}
12
13type t = [`Generic | `Unix] t_internal
14
15type person = {
16 id: string;
17 name: string;
18 birth_date: string option;
19 thumbnail_path: string;
20 is_hidden: bool;
21 unknown: Jsont.json;
22}
23
24(** {1 Client Creation} *)
25
26let create ~requests_session ~base_url ~api_key : t =
27 (* Set API key header on the session *)
28 let requests_session = Requests.set_default_header requests_session "x-api-key" api_key in
29 { base_url; api_key; requests_session }
30
31(** {1 JSON Codecs} *)
32
33(* Jsont codec for person *)
34let person_jsont =
35 let make id name birth_date thumbnail_path is_hidden unknown =
36 { id; name; birth_date; thumbnail_path; is_hidden; unknown }
37 in
38 let id p = p.id in
39 let name p = p.name in
40 let birth_date p = p.birth_date in
41 let thumbnail_path p = p.thumbnail_path in
42 let is_hidden p = p.is_hidden in
43 let unknown p = p.unknown in
44 Jsont.Object.map ~kind:"Person" make
45 |> Jsont.Object.mem "id" Jsont.string ~enc:id
46 |> Jsont.Object.mem "name" Jsont.string ~enc:name
47 |> Jsont.Object.opt_mem "birthDate" Jsont.string ~enc:birth_date
48 |> Jsont.Object.mem "thumbnailPath" Jsont.string ~enc:thumbnail_path
49 |> Jsont.Object.mem "isHidden" Jsont.bool ~enc:is_hidden
50 |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:unknown
51 |> Jsont.Object.finish
52
53type people_response = {
54 total: int;
55 visible: int;
56 people: person list;
57 unknown: Jsont.json;
58}
59
60(* Jsont codec for people_response *)
61let people_response_jsont =
62 let make total visible people unknown =
63 { total; visible; people; unknown }
64 in
65 let total r = r.total in
66 let visible r = r.visible in
67 let people r = r.people in
68 let unknown r = r.unknown in
69 Jsont.Object.map ~kind:"PeopleResponse" make
70 |> Jsont.Object.mem "total" Jsont.int ~enc:total
71 |> Jsont.Object.mem "visible" Jsont.int ~enc:visible
72 |> Jsont.Object.mem "people" (Jsont.list person_jsont) ~enc:people
73 |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:unknown
74 |> Jsont.Object.finish
75
76(** {1 API Functions} *)
77
78let fetch_people { base_url; requests_session; _ } =
79 let open Requests_json_api in
80 let url = base_url / "api/people" in
81 get_json_exn requests_session url people_response_jsont
82
83let fetch_person { base_url; requests_session; _ } ~person_id =
84 let open Requests_json_api in
85 let url = base_url / "api/people" / person_id in
86 get_json_exn requests_session url person_jsont
87
88let download_thumbnail { base_url; requests_session; _ } ~fs ~person_id ~output_path =
89 try
90 let open Requests_json_api in
91 let url = base_url / "api/people" / person_id / "thumbnail" in
92
93 match get_result requests_session url with
94 | Error (status, _body) ->
95 Error (`Msg (sprintf "HTTP error: %d" status))
96 | Ok img_data ->
97 (* Ensure output directory exists *)
98 let dir = Filename.dirname output_path in
99 if not (Sys.file_exists dir) then
100 Unix.mkdir dir 0o755;
101
102 (* Write the image data to file *)
103 let path = Eio.Path.(fs / output_path) in
104 Eio.Path.save ~create:(`Or_truncate 0o644) path img_data;
105
106 Ok ()
107 with
108 | Failure msg -> Error (`Msg msg)
109 | exn -> Error (`Msg (Printexc.to_string exn))
110
111let search_person { base_url; requests_session; _ } ~name =
112 let open Requests_json_api in
113 let encoded_name = Uri.pct_encode name in
114 let url = sprintf "%s/api/search/person?name=%s" base_url encoded_name in
115 get_json_exn requests_session url (Jsont.list person_jsont)