From 678771bb13913889a10e78a9c43a3acb9dfc28b2 Mon Sep 17 00:00:00 2001 From: Koonwen Lee Date: Sat, 15 Feb 2025 20:56:31 +0800 Subject: [PATCH 1/4] remove unused + update file param name --- lib/api_remote.ml | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/lib/api_remote.ml b/lib/api_remote.ml index 4373bfe..4a2b2d4 100644 --- a/lib/api_remote.ml +++ b/lib/api_remote.ml @@ -78,20 +78,6 @@ let update_message ~(ctx : Context.t) ~(msg : Slack_t.update_message_req) = ~name:(sprintf "chat.update (%s,%s)" msg.ts msg.channel) ~ctx ~body `POST "chat.update" Slack_j.read_update_message_res -let www_form_of_files_upload_req (file : Slack_t.files_upload_req) = - let fields = - [ - string_field_val file.channels "channels"; - string_field_val file.content "content"; - string_field_val file.filename "filename"; - string_field_val file.filetype "filetype"; - string_field_val file.initial_comment "initial_comment"; - string_field_val file.thread_ts "thread_ts"; - string_field_val file.title "title"; - ] - in - list_filter_opt fields - let get_permalink ~(ctx : Context.t) ~(req : Slack_t.get_permalink_req) = log#info "getting permalink for channel %s, message_ts %s" req.channel req.message_ts; let args = Web.make_url_args [ "channel", req.channel; "message_ts", req.message_ts ] in @@ -100,22 +86,19 @@ let get_permalink ~(ctx : Context.t) ~(req : Slack_t.get_permalink_req) = ~name:(sprintf "chat.getPermalink (%s, %s)" req.channel req.message_ts) ~ctx `GET api_path Slack_j.read_get_permalink_res -let www_form_of_get_upload_url_ext (req : Slack_t.get_upload_url_ext_req) = - let fields = +let get_upload_url_external ~(ctx : Context.t) ~(req : Slack_t.get_upload_url_ext_req) = + log#info "getting upload url for %s" req.filename; + let args = [ Some ("filename", req.filename); Some ("length", Int.to_string req.length); string_field_val req.alt_txt "alt_txt"; string_field_val req.snippet_type "snippet_type"; ] + |> list_filter_opt in - list_filter_opt fields - -let get_upload_url_external ~(ctx : Context.t) ~(req : Slack_t.get_upload_url_ext_req) = - log#info "getting upload url for %s" req.filename; - let args = www_form_of_get_upload_url_ext req in let data = Web.make_url_args args in - let body = `Raw ("application/x-www-form-urlencoded", data) in + let body = `Form [ "application/x-www-form-urlencoded", data ] in log#info "data to upload req: %s" data; request_token_auth ~ctx ~name:(sprintf "files.getUploadURLExternal (%s)" req.filename) @@ -134,22 +117,22 @@ let complete_upload_external ~(ctx : Context.t) ~(req : Slack_t.complete_upload_ with content [file.content]; Not supporting file upload through form using `file` currently uses web API with access token *) -let upload_file ~(ctx : Context.t) ~(file : Slack_t.files_upload_req) = - match file.filename, file.content with +let upload_file ~(ctx : Context.t) ~(req : Slack_t.files_upload_req) = + match req.filename, req.content with | None, _ | _, None -> Exn.fail "need to supply both filename and content" | Some filename, Some content -> let length = String.length content in - let req = Slack_j.make_get_upload_url_ext_req ~filename ~length () in - ( match%lwt get_upload_url_external ~ctx ~req with + let req' = Slack_j.make_get_upload_url_ext_req ~filename ~length () in + ( match%lwt get_upload_url_external ~ctx ~req:req' with | Error e -> Lwt.return_error e | Ok { upload_url; file_id; _ } -> let raw_file_contents = In_channel.with_open_bin filename (fun ic -> input_all ic) in - let body = `Raw ("", raw_file_contents) in + let body = `Raw ("text/plain", raw_file_contents) in ( match%lwt http_request ~ua:ctx.ua ~body `POST upload_url with | Error e -> slack_lib_fail "upload file failed with: %s" e | Ok _ -> - let files : Slack_t.files_v2 = [ { id = file_id; title = file.title } ] in - let req = Slack_j.make_complete_upload_ext_req ~files ?channels:file.channels ?thread_ts:file.thread_ts () in + let files : Slack_t.files_v2 = [ { id = file_id; title = req.title } ] in + let req = Slack_j.make_complete_upload_ext_req ~files ?channels:req.channels ?thread_ts:req.thread_ts () in ( match%lwt complete_upload_external ~ctx ~req with | Error e -> Lwt.return_error e | Ok { files; _ } -> From a53c224178d6d07c1303d53d81ac4c1ec96dcb79 Mon Sep 17 00:00:00 2001 From: koonwen Date: Sat, 8 Mar 2025 16:55:08 +0800 Subject: [PATCH 2/4] upload_file: support snippets --- lib/api.ml | 2 +- lib/api_remote.ml | 30 ++++++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/api.ml b/lib/api.ml index 5c1dcb9..edcba19 100644 --- a/lib/api.ml +++ b/lib/api.ml @@ -8,7 +8,7 @@ module type S = sig val send_message : ctx:Context.t -> msg:post_message_req -> post_message_res slack_response Lwt.t val send_message_webhook : ctx:Context.t -> url:string -> msg:post_message_req -> unit slack_response Lwt.t val update_message : ctx:Context.t -> msg:update_message_req -> update_message_res slack_response Lwt.t - val upload_file : ctx:Context.t -> file:files_upload_req -> files_upload_res slack_response Lwt.t + val upload_file : ctx:Context.t -> req:files_upload_req -> files_upload_res slack_response Lwt.t val get_permalink : ctx:Context.t -> req:get_permalink_req -> get_permalink_res slack_response Lwt.t (* conversations *) diff --git a/lib/api_remote.ml b/lib/api_remote.ml index 4a2b2d4..82ff961 100644 --- a/lib/api_remote.ml +++ b/lib/api_remote.ml @@ -113,27 +113,33 @@ let complete_upload_external ~(ctx : Context.t) ~(req : Slack_t.complete_upload_ ~name:(sprintf "files.completeUploadExternal (%s)" @@ Slack_j.string_of_files_v2 req.files) ~body `POST "files.completeUploadExternal" Slack_j.read_complete_upload_ext_res -(** [upload_file ctx file] upload [file] to channels noted in [file.channels] - with content [file.content]; Not supporting file upload through form using - `file` currently - uses web API with access token *) +(** [upload_file ctx file] upload [file] to channels noted in + [file.channels] with content [file.content]; Not supporting file + upload through form using `file` currently uses web API with + access token. Snippet can also be sent instead by filling the + content value *) let upload_file ~(ctx : Context.t) ~(req : Slack_t.files_upload_req) = - match req.filename, req.content with - | None, _ | _, None -> Exn.fail "need to supply both filename and content" - | Some filename, Some content -> - let length = String.length content in + match req.filename with + | None -> Exn.fail "need to supply filename" + | Some filename -> + let contents, length = + match req.content with + | Some v -> v, String.length v + | None -> + let raw_file_contents = In_channel.with_open_bin filename (fun ic -> input_all ic) in + raw_file_contents, String.length raw_file_contents + in let req' = Slack_j.make_get_upload_url_ext_req ~filename ~length () in ( match%lwt get_upload_url_external ~ctx ~req:req' with | Error e -> Lwt.return_error e | Ok { upload_url; file_id; _ } -> - let raw_file_contents = In_channel.with_open_bin filename (fun ic -> input_all ic) in - let body = `Raw ("text/plain", raw_file_contents) in + let body = `Raw ("text/plain", contents) in ( match%lwt http_request ~ua:ctx.ua ~body `POST upload_url with | Error e -> slack_lib_fail "upload file failed with: %s" e | Ok _ -> let files : Slack_t.files_v2 = [ { id = file_id; title = req.title } ] in - let req = Slack_j.make_complete_upload_ext_req ~files ?channels:req.channels ?thread_ts:req.thread_ts () in - ( match%lwt complete_upload_external ~ctx ~req with + let req' = Slack_j.make_complete_upload_ext_req ~files ?channels:req.channels ?thread_ts:req.thread_ts () in + ( match%lwt complete_upload_external ~ctx ~req:req' with | Error e -> Lwt.return_error e | Ok { files; _ } -> let f = From 0b7c62756720b7c9ee09a8a2cb08fdf7ed618d5b Mon Sep 17 00:00:00 2001 From: koonwen Date: Sat, 8 Mar 2025 17:15:00 +0800 Subject: [PATCH 3/4] upload_file: alpha equivalent renaming --- examples/sender.ml | 4 ++-- lib/api_local.ml | 6 +++--- lib_test/test.ml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/sender.ml b/examples/sender.ml index 17044d0..e8db20d 100644 --- a/examples/sender.ml +++ b/examples/sender.ml @@ -35,8 +35,8 @@ let send icon_url icon_emoji username channel text = let send_file channels content = let run = let ctx = Common_example.get_ctx_example in - let file = Slack_j.make_files_upload_req ?channels ~content () in - match%lwt Api_remote.upload_file ~ctx ~file with + let req = Slack_j.make_files_upload_req ?channels ~content () in + match%lwt Api_remote.upload_file ~ctx ~req with | Ok res -> printf "file uploaded: %s" res.file.id; ( match res.file.permalink with diff --git a/lib/api_local.ml b/lib/api_local.ml index 954ec87..feec1ca 100644 --- a/lib/api_local.ml +++ b/lib/api_local.ml @@ -59,9 +59,9 @@ let update_message ~ctx:_ ~msg = printf "%s\n" json; Lwt.return_ok { default_update_message_res with channel = msg.channel } -let upload_file ~ctx:_ ~file = - let json = file |> Slack_j.string_of_files_upload_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in - match file.channels with +let upload_file ~ctx:_ ~req = + let json = req |> Slack_j.string_of_files_upload_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in + match req.channels with | Some channels -> printf "will update #%s\n" channels; printf "%s\n" json; diff --git a/lib_test/test.ml b/lib_test/test.ml index 9a7e20a..6d06c04 100644 --- a/lib_test/test.ml +++ b/lib_test/test.ml @@ -138,8 +138,8 @@ let file_list = let process_upload_file (channels, content) = Printf.printf "upload_file_to--------channels: %s--------\n" channels; let ctx = Context.empty_ctx () in - let file : Slack_t.files_upload_req = Slack_j.make_files_upload_req ~channels ~content () in - match%lwt Api.upload_file ~ctx ~file with + let req : Slack_t.files_upload_req = Slack_j.make_files_upload_req ~channels ~content () in + match%lwt Api.upload_file ~ctx ~req with | Ok res -> let json = res |> Slack_j.string_of_files_upload_res |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in print_endline json; From 7c0f66bdb110aefb150161b394e34378e88b56d8 Mon Sep 17 00:00:00 2001 From: koonwen Date: Sat, 8 Mar 2025 18:04:39 +0800 Subject: [PATCH 4/4] fix upload snippet and test --- examples/examples.ml | 12 ++++++++++-- examples/sender.ml | 4 ++-- lib/api_remote.ml | 7 +++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/examples.ml b/examples/examples.ml index 5da9c29..b30cb8c 100644 --- a/examples/examples.ml +++ b/examples/examples.ml @@ -37,6 +37,14 @@ let text = let doc = "text to send" in Arg.(value & opt string "" & info [ "t"; "text" ] ~docv:"TEXT" ~doc) +let content = + let doc = "content/snippet to send" in + Arg.(value & opt (some string) None & info [ "ct"; "content" ] ~docv:"CONTENT" ~doc) + +let filename = + let doc = "filename identifier" in + Arg.(required & opt (some string) None & info [ "f"; "filename" ] ~docv:"FILENAME" ~doc) + let update = let doc = "text to update first message" in Arg.(value & opt string "" & info [ "u"; "update" ] ~docv:"UPDATE" ~doc) @@ -75,9 +83,9 @@ let send = Cmd.v info term let send_file = - let doc = "upload a file using Slack APIs example" in + let doc = "upload a file or snippet using Slack APIs example" in let info = Cmd.info "send_file" ~doc in - let term = Term.(const Sender.send_file $ channels_opt $ text) in + let term = Term.(const Sender.send_file $ content $ channels_opt $ filename) in Cmd.v info term let send_update = diff --git a/examples/sender.ml b/examples/sender.ml index e8db20d..47de73b 100644 --- a/examples/sender.ml +++ b/examples/sender.ml @@ -32,10 +32,10 @@ let send icon_url icon_emoji username channel text = in Lwt_main.run run -let send_file channels content = +let send_file content channels filename = let run = let ctx = Common_example.get_ctx_example in - let req = Slack_j.make_files_upload_req ?channels ~content () in + let req = Slack_j.make_files_upload_req ?channels ?content ~filename () in match%lwt Api_remote.upload_file ~ctx ~req with | Ok res -> printf "file uploaded: %s" res.file.id; diff --git a/lib/api_remote.ml b/lib/api_remote.ml index 82ff961..9444a73 100644 --- a/lib/api_remote.ml +++ b/lib/api_remote.ml @@ -97,12 +97,11 @@ let get_upload_url_external ~(ctx : Context.t) ~(req : Slack_t.get_upload_url_ex ] |> list_filter_opt in - let data = Web.make_url_args args in - let body = `Form [ "application/x-www-form-urlencoded", data ] in - log#info "data to upload req: %s" data; + let args = Web.make_url_args args in + let api_path = sprintf "files.getUploadURLExternal?%s" args in request_token_auth ~ctx ~name:(sprintf "files.getUploadURLExternal (%s)" req.filename) - ~body `POST "files.getUploadURLExternal" Slack_j.read_get_upload_url_ext_res + `POST api_path Slack_j.read_get_upload_url_ext_res let complete_upload_external ~(ctx : Context.t) ~(req : Slack_t.complete_upload_ext_req) = log#info "completing upload url for %s" @@ Slack_j.string_of_files_v2 req.files;