2024-03-16 09:34:29 +01:00
|
|
|
open Pyops
|
|
|
|
open Pytypes
|
|
|
|
open Batteries
|
2024-04-02 14:38:00 +02:00
|
|
|
open Yojson.Safe
|
|
|
|
open Config
|
|
|
|
open Utils
|
2024-04-23 09:35:10 +02:00
|
|
|
open Pam
|
2024-03-16 09:34:29 +01:00
|
|
|
|
2024-04-24 09:45:20 +02:00
|
|
|
let issue_of_json (m_room: Datatypes.MatrixRoom.t) (json): Datatypes.forgejo_issue_data =
|
2024-04-02 14:38:00 +02:00
|
|
|
let open Yojson.Safe.Util in
|
|
|
|
let due_date = json |> member "due_date" |> to_option to_string in
|
2024-04-24 09:45:20 +02:00
|
|
|
let record: Datatypes.forgejo_issue_data = {
|
2024-04-17 18:18:19 +02:00
|
|
|
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 record
|
2024-03-16 09:34:29 +01:00
|
|
|
|
2024-04-02 14:38:00 +02:00
|
|
|
let issues_of_json matrix_room json_str =
|
|
|
|
let open Yojson.Safe.Util in
|
2024-04-17 18:18:19 +02:00
|
|
|
try
|
|
|
|
json_str |> from_string |> to_list |> List.map (issue_of_json matrix_room) |> Result.ok
|
|
|
|
with
|
|
|
|
| Yojson.Json_error msg -> Error [%string "JSON parsing error: %{msg}"]
|
|
|
|
|
|
|
|
module ForgejoUrl = struct
|
|
|
|
type t = {url: string; page: int}
|
|
|
|
let from_id repo_id =
|
|
|
|
{ url = [%string "https://salsa.lezzo.org/api/v1/repos/%{repo_id}/issues?state=open&type=issues&limit=50"];
|
|
|
|
page = 0 }
|
|
|
|
let next_page t = {t with page=t.page+1}
|
|
|
|
let to_string t = [%string "%{t.url}&page=%{t.page#Int}"]
|
|
|
|
end
|
2024-04-02 14:38:00 +02:00
|
|
|
|
2024-04-17 18:18:19 +02:00
|
|
|
type repo_pytuple = {url: ForgejoUrl.t; headers: pyobject}
|
2024-04-02 14:38:00 +02:00
|
|
|
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
|
2024-03-16 09:34:29 +01:00
|
|
|
|> List.map (fun (k, v) -> (k, Py.String.of_string v))
|
2024-04-02 14:38:00 +02:00
|
|
|
|> Py.Dict.of_bindings_string
|
2024-03-16 09:34:29 +01:00
|
|
|
|
2024-04-02 14:38:00 +02:00
|
|
|
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} ->
|
2024-04-17 18:18:19 +02:00
|
|
|
(matrix_room, {url=ForgejoUrl.from_id forgejo_id; headers=make_headers base64_password}))
|
2024-04-02 14:38:00 +02:00
|
|
|
|> StringMap.of_list
|
|
|
|
in
|
|
|
|
{requests=requests; repos=urls}
|
2024-03-16 09:34:29 +01:00
|
|
|
|
2024-04-17 18:18:19 +02:00
|
|
|
let pyprint () =
|
|
|
|
let builtins = Py.Eval.get_builtins () in
|
|
|
|
let p = Py.Dict.find_string builtins "print" in
|
|
|
|
Py.Callable.to_function p
|
|
|
|
|
|
|
|
let extract_pagination resp =
|
|
|
|
let key = Py.String.of_string "X-Total-Count" in
|
|
|
|
resp
|
|
|
|
.@$("headers")
|
|
|
|
.&("get") [|key|] (* not really a pydict, so need to use `get` *)
|
|
|
|
|> Py.Object.to_string
|
2024-05-01 12:03:26 +02:00
|
|
|
|> int_of_string_opt
|
2024-04-17 18:18:19 +02:00
|
|
|
|
2024-04-02 14:38:00 +02:00
|
|
|
let make_get_request {requests; repos} =
|
2024-03-16 09:34:29 +01:00
|
|
|
let get = Py.Module.get_function_with_keywords requests "get" in
|
2024-04-17 18:18:19 +02:00
|
|
|
|
|
|
|
|
2024-04-24 09:45:20 +02:00
|
|
|
let rec fold_fn (accum: (Datatypes.forgejo_issue_data list)) = function
|
2024-04-17 18:18:19 +02:00
|
|
|
| [] -> Ok accum
|
|
|
|
| (m_room_string, {url; headers})::rest ->
|
|
|
|
let pyurl = url |> ForgejoUrl.to_string |> Py.String.of_string in
|
|
|
|
let resp = get [|pyurl|] [("headers", headers)] in
|
2024-04-02 14:38:00 +02:00
|
|
|
let jsontext =
|
|
|
|
resp.@$("text")
|
|
|
|
|> Py.String.to_string
|
|
|
|
in
|
2024-04-17 18:18:19 +02:00
|
|
|
let target_items_total = extract_pagination resp in
|
2024-04-02 14:38:00 +02:00
|
|
|
let matrix_room = Datatypes.MatrixRoom.make m_room_string in
|
2024-04-17 18:18:19 +02:00
|
|
|
let issues = issues_of_json matrix_room jsontext in
|
2024-05-01 12:03:26 +02:00
|
|
|
match target_items_total, issues with
|
|
|
|
| None, _ -> Error "Can't extract pagination"
|
|
|
|
| _, Error err ->
|
2024-04-17 18:18:19 +02:00
|
|
|
Error err
|
2024-05-01 12:03:26 +02:00
|
|
|
| Some target_items_total, Ok target_issues ->
|
2024-04-17 18:18:19 +02:00
|
|
|
let n_received = List.length target_issues in
|
|
|
|
let accum' = target_issues@accum in
|
|
|
|
let urls =
|
|
|
|
if n_received <> target_items_total then
|
|
|
|
(m_room_string, {url=ForgejoUrl.next_page url; headers=headers})::rest
|
|
|
|
else
|
|
|
|
rest
|
|
|
|
in fold_fn accum' urls
|
|
|
|
|
|
|
|
in
|
|
|
|
StringMap.to_list repos
|
|
|
|
|> fold_fn []
|