Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deprecate file.upload and implement new apis #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/api.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ module type S = sig
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
[@@deprecated "Use get_upload_url_external with \
complete_upload_external as per \
https://api.slack.com/messaging/files#uploading_files. Otherwise, \
there is upload_file_v2 convenience function"]

val get_upload_url_external : ctx:Context.t -> req:get_upload_url_ext_req -> get_upload_url_ext_res slack_response Lwt.t
val complete_upload_external : ctx:Context.t -> req:complete_upload_ext_req -> complete_upload_ext_res slack_response Lwt.t
val upload_file_v2 : ctx:Context.t -> file:files_upload_req -> files_upload_res slack_response Lwt.t

(* conversations *)
val get_replies :
Expand Down
33 changes: 33 additions & 0 deletions lib/api_local.ml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ let default_files_res : Slack_t.file =

let default_files_upload_res : Slack_t.files_upload_res = { ok = true; file = default_files_res }

let default_files_upload_res_v2 : Slack_t.complete_upload_ext_res =
{ ok = true; files = [ { id = default_files_res.id; title = default_files_res.title } ] }

let send_message ~ctx:_ ~msg =
let json = msg |> Slack_j.string_of_post_message_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in
printf "will notify #%s\n" msg.channel;
Expand Down Expand Up @@ -65,6 +68,36 @@ let upload_file ~ctx:_ ~file =
Lwt.return_ok { default_files_upload_res with file = { default_files_res with channels = [ channels ] } }
| None -> Lwt.return_error (`Other "invalid file upload")

let get_upload_url_external ~ctx:_ ~(req : Slack_t.get_upload_url_ext_req) =
let json =
req |> Slack_j.string_of_get_upload_url_ext_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string
in
printf "getting upload url for %s\n" req.filename;
printf "%s\n" json;
Lwt.return_ok Slack_t.{ ok = true; upload_url = "http://fake-upload-url.com"; file_id = "file_id" }

let complete_upload_external ~ctx:_ ~(req : Slack_t.complete_upload_ext_req) =
let json =
req |> Slack_j.string_of_complete_upload_ext_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string
in
printf "complete upload for %s in channel:%s or ts:%s\n" (Slack_j.string_of_files_v2 req.files)
(Option.default "NULL" req.channel_id) (Option.default "NULL" req.thread_ts);
printf "%s\n" json;
Lwt.return_ok default_files_upload_res_v2

let upload_file_v2 ~ctx:_ ~(file : Slack_t.files_upload_req) =
let json = file |> Slack_j.string_of_files_upload_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in
match file.channels with
| Some channels ->
if List.length (String.split_on_char ',' channels) <> 1 then
Lwt.return_error (`Other "only allowed to specify 1 channel")
else (
printf "will update #%s\n" channels;
printf "%s\n" json;
Lwt.return_ok { default_files_upload_res with file = { default_files_res with channels = [ channels ] }}
)
| None -> Lwt.return_error (`Other "invalid file upload")

let join_conversation ~ctx:_ ~(channel : Slack_t.conversations_join_req) =
printf "joining #%s...\n" channel.channel;
let url = Filename.concat cache_dir (sprintf "%s_join" channel.channel) in
Expand Down
64 changes: 64 additions & 0 deletions lib/api_remote.ml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,70 @@ let upload_file ~(ctx : Context.t) ~(file : Slack_t.files_upload_req) =
~name:(sprintf "file.upload (%s)" @@ Option.default "<NO CHANNEL>" file.channels)
~body `POST "files.upload" Slack_j.read_files_upload_res

let www_form_of_get_upload_url_ext (req : Slack_t.get_upload_url_ext_req) =
let fields =
[
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";
]
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
log#info "data to upload req: %s" data;
request_token_auth ~ctx
~name:(sprintf "files.getUploadURLExternal (%s)" req.filename)
~body `POST "files.getUploadURLExternal" 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;
let data = Slack_j.string_of_complete_upload_ext_req req in
let body = `Raw ("application/json", data) in
log#info "data to upload req: %s" data;
request_token_auth ~ctx
~name:(sprintf "files.completeUploadExternal (%s)" @@ Slack_j.string_of_files_v2 req.files)
~body `POST "files.completeUploadExternal" Slack_j.read_complete_upload_ext_res

(** NOTE: this api only can specify one channel_id unlike in the deprecated version *)
let upload_file_v2 ~(ctx : Context.t) ~(file : Slack_t.files_upload_req) =
match file.filename, file.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
| Error e -> Lwt.return_error e
| Ok { upload_url; file_id; _ } ->
let body = `Form [ "file", filename ] 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.file_v2 = { id = file_id; title = file.title } in
let req =
Slack_j.make_complete_upload_ext_req ~files:[ files ] ?channel_id:file.channels ?thread_ts:file.thread_ts ()
in
( match%lwt complete_upload_external ~ctx ~req with
| Error e -> Lwt.return_error e
| Ok { files; _ } ->
let f =
match files with
| [] -> slack_lib_fail "empty files on complete_upload_external response"
| [ f ] -> f
| f :: _ ->
log#warn "got more than 1 file in response, returning top";
f
in
Lwt.return_ok Slack_t.{ ok = true; file = Slack_j.make_file ~id:f.id ?title:f.title () }
)
)
)

(** [join_conversation ctx channel ] will join the token owner
[ctx.secrets.slack_access_token] to the [channel]. *)
let join_conversation ~(ctx : Context.t) ~(channel : Slack_t.conversations_join_req) =
Expand Down
34 changes: 33 additions & 1 deletion lib/slack.atd
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ type files_upload_req <ocaml attr="deriving make"> = {
?title: string nullable;
}

type file = {
type file <ocaml attr="deriving make"> = {
id: string;
?name: string nullable;
?title: string nullable;
Expand All @@ -151,6 +151,38 @@ type files_upload_res = {
file: file;
}

type file_v2 = {
id: string;
?title : string nullable
}

type files_v2 = file_v2 list

type get_upload_url_ext_req <ocaml attr="deriving make"> = {
filename: string;
length: int;
?alt_txt: string nullable;
?snippet_type: string nullable
}

type get_upload_url_ext_res = {
ok: bool;
upload_url: string;
file_id: string
}

type complete_upload_ext_req <ocaml attr="deriving make"> = {
files: files_v2;
?channel_id : string nullable;
?initial_comment: string nullable;
?thread_ts: string nullable
}

type complete_upload_ext_res = {
ok: bool;
files: files_v2;
}

type conversations_info_req <ocaml attr="deriving make"> = {
channel: string;
?include_locale: bool nullable;
Expand Down
Loading