Google Docs API client for OCaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 96 lines 2.5 kB view raw view rendered
1# gdocs 2 3Google Docs API client for OCaml. 4 5`gdocs` implements a small, opinionated slice of the [Google Docs 6REST API][gdocs-api]: fetching documents by ID and extracting their 7content as plain text or Markdown. Authentication is delegated to 8[`gauth`][gauth]; reading requires the 9`.../auth/documents.readonly` OAuth scope. 10 11[gdocs-api]: https://developers.google.com/docs/api/reference/rest 12[gauth]: https://tangled.org/gazagnaire.org/ocaml-gauth 13 14## Installation 15 16Install with opam: 17 18<!-- $MDX skip --> 19```sh 20$ opam install gdocs 21``` 22 23If opam cannot find the package, it may not yet be released in the 24public `opam-repository`. Add the overlay repository, then install 25it: 26 27<!-- $MDX skip --> 28```sh 29$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git 30$ opam update 31$ opam install gdocs 32``` 33 34## Usage 35 36The main entry points are `Gdocs.get`, `Document.title`, 37`Document.to_text`, and `Markdown.of_document`: 38 39```ocaml 40let fetch_markdown http ~token ~document_id = 41 match Gdocs.get http ~token document_id with 42 | Error (`Msg m) -> Error m 43 | Ok doc -> 44 let body = Gdocs.Markdown.of_document doc in 45 Ok (Gdocs.Document.title doc, body) 46``` 47 48Wire that up with `gauth` and Eio for a full flow: 49 50```ocaml 51let run env ~key_path ~document_id = 52 Eio.Switch.run @@ fun sw -> 53 let http = Requests.v ~sw env in 54 let clock = Eio.Stdenv.clock env in 55 match Gauth.Service_account.of_file key_path with 56 | Error (`Msg m) -> failwith m 57 | Ok key -> 58 match 59 Gauth.Service_account.token http ~clock 60 ~scopes:[ Gdocs.scope_readonly ] key 61 with 62 | Error (`Msg m) -> failwith m 63 | Ok token -> 64 match Gdocs.get http ~token document_id with 65 | Ok doc -> 66 Fmt.pr "# %s@.@.%s@." 67 (Gdocs.Document.title doc) 68 (Gdocs.Markdown.of_document doc) 69 | Error (`Msg m) -> Fmt.pr "fetch failed: %s@." m 70``` 71 72### Plain text 73 74`Document.to_text` concatenates every `textRun` in paragraph order; 75the API already emits trailing newlines, so the result is 76paragraph-terminated: 77 78```ocaml 79let title_and_text doc = 80 Gdocs.Document.title doc, Gdocs.Document.to_text doc 81``` 82 83### Scopes 84 85```ocaml 86let readonly = Gdocs.scope_readonly 87let readwrite = Gdocs.scope_readwrite 88``` 89 90HTTP errors surface with the response status in the `Msg` payload: 91`401` for an invalid or expired token, `403` for missing scopes or 92no access, `404` for an unknown document id. 93 94## Licence 95 96MIT