OCaml bindings to the Peertube ActivityPub video sharing API
at main 166 lines 5.3 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6open Cmdliner 7 8let app_name = "peertube" 9 10(** {1 Common Options} *) 11 12let profile_arg = 13 let doc = "Profile name to use for authentication." in 14 Arg.(value & opt (some string) None & info ["profile"; "p"] ~docv:"PROFILE" ~doc) 15 16let server_url_arg = 17 let doc = "PeerTube server URL (e.g., https://peertube.example.com)." in 18 Arg.(required & opt (some string) None & info ["server"; "s"] ~docv:"URL" ~doc) 19 20let username_arg = 21 let doc = "Username for authentication." in 22 Arg.(required & opt (some string) None & info ["username"; "u"] ~docv:"USER" ~doc) 23 24let password_arg = 25 let doc = "Password for authentication. For security, prefer using the environment variable PEERTUBE_PASSWORD." in 26 Arg.(value & opt (some string) None & info ["password"] ~docv:"PASS" ~doc) 27 28(* Requests config term *) 29let requests_config_term fs = 30 Requests.Cmd.config_term app_name fs 31 32(** {1 Login Command} *) 33 34let login_cmd env fs = 35 let login_action profile server_url username password requests_config = 36 Error.wrap @@ fun () -> 37 Eio.Switch.run @@ fun sw -> 38 let password = match password with 39 | Some p -> p 40 | None -> 41 match Sys.getenv_opt "PEERTUBE_PASSWORD" with 42 | Some p -> p 43 | None -> Error.fail "Password required. Use --password or set PEERTUBE_PASSWORD environment variable." 44 in 45 let requests_config = Some requests_config in 46 let client = Client.login_password ~sw ~env ?requests_config ?profile ~server_url ~username ~password () in 47 Fmt.pr "@[<v>%a Logged in successfully@,%a@]@." 48 Fmt.(styled (`Fg `Green) string) "[OK]" 49 Session.pp (Client.session client); 50 0 51 in 52 let term = Term.(const login_action $ profile_arg $ server_url_arg $ username_arg $ password_arg $ requests_config_term fs) in 53 let info = Cmd.info "login" 54 ~doc:"Login to a PeerTube server" 55 ~man:[ 56 `S Manpage.s_description; 57 `P "Authenticate with a PeerTube server using username and password."; 58 `P "The OAuth client credentials are automatically retrieved from the server."; 59 `S Manpage.s_examples; 60 `Pre " peertube auth login -s https://peertube.example.com -u myuser"; 61 `P "You can also set the password via environment variable:"; 62 `Pre " PEERTUBE_PASSWORD=mypass peertube auth login -s https://peertube.example.com -u myuser"; 63 ] 64 in 65 Cmd.v info term 66 67(** {1 Logout Command} *) 68 69let logout_cmd _env fs = 70 let logout_action profile = 71 Error.wrap @@ fun () -> 72 Session.clear fs ?profile (); 73 Fmt.pr "@[%a Logged out@]@." Fmt.(styled (`Fg `Green) string) "[OK]"; 74 0 75 in 76 let term = Term.(const logout_action $ profile_arg) in 77 let info = Cmd.info "logout" 78 ~doc:"Logout from PeerTube" 79 ~man:[ 80 `S Manpage.s_description; 81 `P "Remove saved authentication credentials."; 82 ] 83 in 84 Cmd.v info term 85 86(** {1 Status Command} *) 87 88let status_cmd _env fs = 89 let status_action profile = 90 Error.wrap @@ fun () -> 91 match Session.load fs ?profile () with 92 | None -> 93 Fmt.pr "@[Not logged in@]@."; 94 1 95 | Some session -> 96 Fmt.pr "@[<v>%a@]@." Session.pp session; 97 0 98 in 99 let term = Term.(const status_action $ profile_arg) in 100 let info = Cmd.info "status" 101 ~doc:"Show current authentication status" 102 ~man:[ 103 `S Manpage.s_description; 104 `P "Display information about the current session."; 105 ] 106 in 107 Cmd.v info term 108 109(** {1 Profiles Command} *) 110 111let profiles_cmd _env fs = 112 let profiles_action () = 113 Error.wrap @@ fun () -> 114 let profiles = Session.list_profiles fs in 115 let current = Session.get_current_profile fs in 116 if profiles = [] then begin 117 Fmt.pr "@[No profiles found. Use 'peertube auth login' to create one.@]@."; 118 0 119 end else begin 120 Fmt.pr "@[<v>%a@]@." 121 Fmt.(list ~sep:(any "@,") (fun ppf p -> 122 if p = current then 123 pf ppf "* %a (current)" (styled (`Fg `Green) string) p 124 else 125 pf ppf " %s" p)) profiles; 126 0 127 end 128 in 129 let term = Term.(const profiles_action $ const ()) in 130 let info = Cmd.info "profiles" 131 ~doc:"List available profiles" 132 ~man:[ 133 `S Manpage.s_description; 134 `P "List all saved authentication profiles."; 135 ] 136 in 137 Cmd.v info term 138 139(** {1 Auth Command Group} *) 140 141let auth_cmd env fs = 142 let info = Cmd.info "auth" 143 ~doc:"Authentication commands" 144 ~man:[ 145 `S Manpage.s_description; 146 `P "Commands for managing PeerTube authentication."; 147 ] 148 in 149 Cmd.group info [ 150 login_cmd env fs; 151 logout_cmd env fs; 152 status_cmd env fs; 153 profiles_cmd env fs; 154 ] 155 156(** {1 Client Helper} *) 157 158(** [with_client ~sw ~env ~fs ?profile f] loads a session and creates a client, 159 then calls [f] with the client. Exits with an error if not logged in. *) 160let with_client ~sw ~env ~fs ?requests_config ?profile f = 161 match Session.load fs ?profile () with 162 | None -> 163 Error.fail "Not logged in. Use 'peertube auth login' first." 164 | Some session -> 165 let client = Client.resume ~sw ~env ?requests_config ?profile ~session () in 166 f client