open Pyops open Pytypes open Batteries open Yojson.Safe open Config open Utils let forgejo_url repo_id = [%string "https://salsa.lezzo.org/api/v1/repos/%{repo_id}/issues?state=open&type=issues"] let issue_of_json (m_room: Datatypes.MatrixRoom.t) (json): Datatypes.reminder option = let open Yojson.Safe.Util in let due_date = json |> member "due_date" |> to_option to_string in match due_date with | None -> None | Some due_date -> let record: Datatypes.reminder = { url = json |> member "url" |> to_string; title = json |> member "title" |> to_string; body = json |> member "body" |> to_string; matrix_target = m_room; due_date = due_date } in Some record let issues_of_json matrix_room json_str = let open Yojson.Safe.Util in try json_str |> from_string |> to_list |> List.map (issue_of_json matrix_room) |> List.filter_map identity |> Result.ok with | Yojson.Json_error msg -> Error [%string "JSON parsing error: %{msg}"] type repo_pytuple = {url: pyobject; headers: pyobject} type http_actor = {requests: pyobject; repos: repo_pytuple StringMap.t} let make_headers base64_password = let headers = [("accept", "application/json"); ("authorization", [%string "Basic %{base64_password}"])] in headers |> List.map (fun (k, v) -> (k, Py.String.of_string v)) |> Py.Dict.of_bindings_string let init (repos: Config.repo_data list) = let _ = Py.initialize () in let requests = Py.import "requests" in let urls = repos |> List.map (fun {forgejo_id; base64_password; matrix_room} -> (matrix_room, {url=forgejo_url forgejo_id |> Py.String.of_string; headers=make_headers base64_password})) |> StringMap.of_list in {requests=requests; repos=urls} let make_get_request {requests; repos} = let get = Py.Module.get_function_with_keywords requests "get" in let fold_fn = (fun m_room_string {url; headers} acc -> let resp = get [|url|] [("headers", headers)] in let jsontext = resp.@$("text") |> Py.String.to_string in let matrix_room = Datatypes.MatrixRoom.make m_room_string in let value = issues_of_json matrix_room jsontext |> Result.map Datatypes.forgejo_issues |> Result.map_error Datatypes.forgejo_error (*TODO: maybe not really a forgejo error, more like internal *) in value::acc) in StringMap.fold fold_fn repos []