README

marianoguerra/slack/client does not have a README file

#
Client

pub struct Client {
transport : &
Transport

token : String
base_url : String
bool_style :
BoolStyle

extra_headers : Map[String, String]
team_id : String?
}

#
Client::api_test

https://docs.slack.dev/reference/methods/api.test

Echoes its arguments back. Genuinely useful: it is the one call that proves the transport works without needing a valid token.

#
Client::auth_revoke

https://docs.slack.dev/reference/methods/auth.revoke dry_run is Slack's test argument, renamed because test is a MoonBit keyword. Set it to check whether the token WOULD be revoked without revoking it.

#
Client::auth_test

https://docs.slack.dev/reference/methods/auth.test

The call to make first. It answers with the team, the user and the bot id the token belongs to -- which is the only way to find out what a token actually is, since the xoxb- prefix says almost nothing.

#
Client::bookmarks_add

async fn Client::bookmarks_add(self : Client, channel_id~ : String, title~ : String, type_~ : String, link? : String, emoji? : String, entity_id? : String, parent_id? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/bookmarks.add

#
Client::bookmarks_list

https://docs.slack.dev/reference/methods/bookmarks.list

#
Client::call

Call any Web API method.

The escape hatch that keeps all 326 methods reachable: the typed builders below cover the families most apps use, and everything else is this.

Raises rather than returning ok: false as a value. A refusal from Slack is an error in every sense that matters to a caller -- they asked for something and did not get it -- and making it a return value means every call site either checks or silently proceeds on a message that was never posted. PlatformError carries the whole response for the cases that want it.

#
Client::chat_delete

async fn Client::chat_delete(self : Client, channel~ : String, ts~ : String, as_user? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.delete

#
Client::chat_delete_scheduled_message

async fn Client::chat_delete_scheduled_message(self : Client, channel~ : String, scheduled_message_id~ : String, as_user? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.deleteScheduledMessage
async fn Client::chat_get_permalink(self : Client, channel~ : String, message_ts~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.getPermalink

#
Client::chat_me_message

async fn Client::chat_me_message(self : Client, channel~ : String, text~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.meMessage

#
Client::chat_post_ephemeral

async fn Client::chat_post_ephemeral(self : Client, channel~ : String, user~ : String, text? : String, blocks? : Array[
LayoutBlock
], attachments? : Json, thread_ts? : String, parse? : String, link_names? : Bool, username? : String, icon_emoji? : String, icon_url? : String, markdown_text? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.postEphemeral

Visible to one user, and never stored. There is no ts to update or delete afterwards.

#
Client::chat_post_message

async fn Client::chat_post_message(self : Client, channel~ : String, text? : String, blocks? : Array[
LayoutBlock
], attachments? : Json, thread_ts? : String, reply_broadcast? : Bool, unfurl_links? : Bool, unfurl_media? : Bool, mrkdwn? : Bool, parse? : String, link_names? : Bool, username? : String, icon_emoji? : String, icon_url? : String, metadata? : Json, markdown_text? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.postMessage

text is optional in the schema but should almost always be set even when blocks is: it is what shows in notifications, in the sidebar preview and in clients that cannot render blocks. node-slack-sdk warns when it is missing; this library documents it here instead of logging at you.

#
Client::chat_schedule_message

async fn Client::chat_schedule_message(self : Client, channel~ : String, post_at~ : Int64, text? : String, blocks? : Array[
LayoutBlock
], attachments? : Json, thread_ts? : String, reply_broadcast? : Bool, unfurl_links? : Bool, unfurl_media? : Bool, metadata? : Json, markdown_text? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.scheduleMessage

#
Client::chat_scheduled_messages_list

async fn Client::chat_scheduled_messages_list(self : Client, channel? : String, cursor? : String, limit? : Int, latest? : String, oldest? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.scheduledMessages.list

#
Client::chat_unfurl

async fn Client::chat_unfurl(self : Client, channel~ : String, ts~ : String, unfurls~ : Json, user_auth_required? : Bool, user_auth_message? : String, user_auth_url? : String, user_auth_blocks? : Array[
LayoutBlock
]) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.unfurl

user_auth_blocks is spelled that way on the wire; java-slack-sdk's RequestFormBuilderTest has a case for it precisely because the field name does not match the Java one.

#
Client::chat_update

async fn Client::chat_update(self : Client, channel~ : String, ts~ : String, text? : String, blocks? : Array[
LayoutBlock
], attachments? : Json, link_names? : Bool, parse? : String, metadata? : Json, markdown_text? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/chat.update

Note what an omitted blocks means here: the existing blocks stay. To REMOVE them, pass an empty list -- which serialises to [] rather than vanishing, exactly as java-slack-sdk pins.

#
Client::conversations_archive

async fn Client::conversations_archive(self : Client, channel~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.archive

#
Client::conversations_close

https://docs.slack.dev/reference/methods/conversations.close

#
Client::conversations_create

async fn Client::conversations_create(self : Client, name~ : String, is_private? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.create

#
Client::conversations_history

async fn Client::conversations_history(self : Client, channel~ : String, cursor? : String, limit? : Int, latest? : String, oldest? : String, inclusive? : Bool, include_all_metadata? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.history

#
Client::conversations_history_all

async fn Client::conversations_history_all(self : Client, channel~ : String, latest? : String, oldest? : String, page_size? : Int, max_pages? : Int) -> Array[Json] raise
SlackError

Every message in a channel, oldest page last.

#
Client::conversations_info

async fn Client::conversations_info(self : Client, channel~ : String, include_locale? : Bool, include_num_members? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.info

#
Client::conversations_invite

async fn Client::conversations_invite(self : Client, channel~ : String, users~ : Array[String], force? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.invite

users is comma-joined, up to 1,000 ids. java-slack-sdk joins this field by hand for exactly this reason.

#
Client::conversations_join

https://docs.slack.dev/reference/methods/conversations.join

#
Client::conversations_kick

async fn Client::conversations_kick(self : Client, channel~ : String, user~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.kick

#
Client::conversations_leave

https://docs.slack.dev/reference/methods/conversations.leave

#
Client::conversations_list

async fn Client::conversations_list(self : Client, types? : Array[String], exclude_archived? : Bool, limit? : Int, cursor? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.list

types is comma-joined on the wire: public_channel,private_channel,mpim,im. That is a per-field fact from Slack's docs, which is why it is Csv here and not a JSON array.

#
Client::conversations_list_all

async fn Client::conversations_list_all(self : Client, types? : Array[String], exclude_archived? : Bool, page_size? : Int, max_pages? : Int) -> Array[Json] raise
SlackError

Every conversation, across every page.

Tier 2 at 20 requests a minute, and a large workspace has tens of thousands of channels -- so this is the call that will get you rate-limited if anything does. Pass max_pages when you only need a sample.

#
Client::conversations_mark

async fn Client::conversations_mark(self : Client, channel~ : String, ts~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.mark

#
Client::conversations_members

async fn Client::conversations_members(self : Client, channel~ : String, cursor? : String, limit? : Int) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.members

#
Client::conversations_members_all

async fn Client::conversations_members_all(self : Client, channel~ : String, page_size? : Int, max_pages? : Int) -> Array[Json] raise
SlackError

#
Client::conversations_open

async fn Client::conversations_open(self : Client, channel? : String, users? : Array[String], return_im? : Bool, prevent_creation? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.open

With users, opens a DM or group DM; with channel, resumes an existing one.

#
Client::conversations_rename

async fn Client::conversations_rename(self : Client, channel~ : String, name~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.rename

#
Client::conversations_replies

async fn Client::conversations_replies(self : Client, channel~ : String, ts~ : String, cursor? : String, limit? : Int, latest? : String, oldest? : String, inclusive? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.replies

ts is the PARENT message's timestamp. The first item that comes back is that parent, not the first reply.

#
Client::conversations_set_purpose

async fn Client::conversations_set_purpose(self : Client, channel~ : String, purpose~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.setPurpose

#
Client::conversations_set_topic

async fn Client::conversations_set_topic(self : Client, channel~ : String, topic~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/conversations.setTopic

#
Client::files_complete_upload_external

async fn Client::files_complete_upload_external(self : Client, files~ : Json, channel_id? : String, initial_comment? : String, thread_ts? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/files.completeUploadExternal

#
Client::files_delete

https://docs.slack.dev/reference/methods/files.delete

#
Client::files_get_upload_url_external

async fn Client::files_get_upload_url_external(self : Client, filename~ : String, length~ : Int, alt_txt? : String, snippet_type? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/files.getUploadURLExternal

Step one of the upload dance: ask for a URL, PUT the bytes to it yourself, then call files.completeUploadExternal. The PUT is not a Web API call and this library does not do it -- see the README.

#
Client::files_info

async fn Client::files_info(self : Client, file~ : String, cursor? : String, limit? : Int) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/files.info

#
Client::files_list

async fn Client::files_list(self : Client, channel? : String, user? : String, types? : Array[String], ts_from? : String, ts_to? : String, count? : Int, page? : Int) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/files.list

#
Client::interpret

Turn one HTTP response into a result or an error.

Separate from call and synchronous, so the status-handling rules are testable without a transport at all.

#
Client::new

fn Client::new(transport : &
Transport
, token : String, base_url? : String, bool_style? :
BoolStyle
, extra_headers? : Map[String, String], team_id? : String) -> Client

#
Client::paginate

async fn Client::paginate(self : Client, api_method : String, params :
Params
, on_page : (
ApiResponse
) -> Bool, page_size? : Int, cursor? : String, max_pages? : Int) -> Int raise
SlackError

Walk every page of a paginated method.

on_page is called with each page and returns false to stop early -- node-slack-sdk's shouldStop, inverted so that the common case is _ => true. Returns the number of pages fetched.

A callback rather than an iterator because MoonBit's async iteration would force this whole package to depend on a runtime; the callback costs one closure and keeps @client buildable on wasm.

#
Client::paginate_collect

async fn Client::paginate_collect(self : Client, api_method : String, params :
Params
, key : String, page_size? : Int, max_pages? : Int) -> Array[Json] raise
SlackError

Walk every page and concatenate the items under key.

key is the collection's name in the response -- channels for conversations.list, members for users.list, messages for conversations.history. Slack has no single name for it, so it cannot be inferred.

#
Client::pins_add

async fn Client::pins_add(self : Client, channel~ : String, timestamp? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/pins.add

#
Client::pins_list

https://docs.slack.dev/reference/methods/pins.list

#
Client::pins_remove

async fn Client::pins_remove(self : Client, channel~ : String, timestamp? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/pins.remove

#
Client::reactions_add

async fn Client::reactions_add(self : Client, channel~ : String, timestamp~ : String, name~ : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/reactions.add

name is the shortcode WITHOUT colons: thumbsup, not :thumbsup:.

#
Client::reactions_get

async fn Client::reactions_get(self : Client, channel? : String, timestamp? : String, file? : String, file_comment? : String, full? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/reactions.get

#
Client::reactions_list

async fn Client::reactions_list(self : Client, user? : String, cursor? : String, limit? : Int, full? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/reactions.list

#
Client::reactions_remove

async fn Client::reactions_remove(self : Client, name~ : String, channel? : String, timestamp? : String, file? : String, file_comment? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/reactions.remove

#
Client::team_info

async fn Client::team_info(self : Client, team? : String, domain? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/team.info

#
Client::team_profile_get

https://docs.slack.dev/reference/methods/team.profile.get

#
Client::usergroups_create

async fn Client::usergroups_create(self : Client, name~ : String, handle? : String, description? : String, channels? : Array[String], include_count? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/usergroups.create

#
Client::usergroups_list

async fn Client::usergroups_list(self : Client, include_disabled? : Bool, include_count? : Bool, include_users? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/usergroups.list

#
Client::usergroups_users_list

async fn Client::usergroups_users_list(self : Client, usergroup~ : String, include_disabled? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/usergroups.users.list

#
Client::usergroups_users_update

async fn Client::usergroups_users_update(self : Client, usergroup~ : String, users~ : Array[String], include_count? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/usergroups.users.update

Replaces the membership wholesale; it is not an "add". Reading usergroups.users.list first and sending the union is on the caller.

#
Client::users_conversations

async fn Client::users_conversations(self : Client, user? : String, types? : Array[String], exclude_archived? : Bool, cursor? : String, limit? : Int) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/users.conversations

#
Client::users_get_presence

https://docs.slack.dev/reference/methods/users.getPresence

#
Client::users_info

async fn Client::users_info(self : Client, user~ : String, include_locale? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/users.info

#
Client::users_list

async fn Client::users_list(self : Client, cursor? : String, limit? : Int, include_locale? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/users.list

#
Client::users_list_all

async fn Client::users_list_all(self : Client, include_locale? : Bool, page_size? : Int, max_pages? : Int) -> Array[Json] raise
SlackError

Every member, across every page. The collection is called members, not users.

#
Client::users_lookup_by_email

https://docs.slack.dev/reference/methods/users.lookupByEmail

#
Client::users_profile_get

async fn Client::users_profile_get(self : Client, user? : String, include_labels? : Bool) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/users.profile.get

#
Client::users_profile_set

async fn Client::users_profile_set(self : Client, user? : String, profile? : Json, name? : String, value? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/users.profile.set

#
Client::users_set_presence

https://docs.slack.dev/reference/methods/users.setPresence

#
Client::views_open

async fn Client::views_open(self : Client, trigger_id~ : String, view~ : Json) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/views.open

trigger_id expires three seconds after the interaction that produced it. A modal that "sometimes fails to open" is almost always this.

#
Client::views_publish

async fn Client::views_publish(self : Client, user_id~ : String, view~ : Json, hash? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/views.publish

The App Home tab. hash is the same lost-update guard as on views.update.

#
Client::views_push

async fn Client::views_push(self : Client, trigger_id~ : String, view~ : Json) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/views.push

#
Client::views_update

async fn Client::views_update(self : Client, view~ : Json, view_id? : String, external_id? : String, hash? : String) ->
ApiResponse
raise
SlackError

https://docs.slack.dev/reference/methods/views.update

Identify the view by view_id or by external_id, not both. hash guards against a lost update when two handlers race.

#
Paginator

pub struct Paginator {
page_size : Int
cursor : String?
finished : Bool
pages : Int
}

#
Paginator::accept

Record a page and work out whether there is another.

An absent cursor ends the walk, and so does an EMPTY one: Slack sends "next_cursor": "" on the last page, and a client that treats that as a cursor asks for the same page forever. node-slack-sdk's paginationOptionsForNextPage checks for both, and so does this.

#
Paginator::cursor

fn Paginator::cursor(self : Paginator) -> String?

#
Paginator::is_finished

fn Paginator::is_finished(self : Paginator) -> Bool

#
Paginator::new

fn Paginator::new(page_size? : Int, cursor? : String) -> Paginator

A paginator over one method.

cursor resumes a walk that was interrupted -- a job that paged through 40,000 conversations and died at 30,000 should not start again.

#
Paginator::next

The extra parameters for the next request, or None when there are no more pages.

limit is sent on EVERY request, including the first. node-slack-sdk adds it only from the second request onward, which means page one comes back at whatever default the method happens to have (usually 100) and every later page holds 200 -- a difference the caller never asked for and will only notice as an odd row count. Sending it consistently is a deliberate divergence.

#
Paginator::pages

fn Paginator::pages(self : Paginator) -> Int

#
Paginator::stop

fn Paginator::stop(self : Paginator) -> Unit

Stop early, whatever the cursor says. The caller's own decision -- "I have enough", "I found what I was looking for" -- rather than Slack's.

#
default_page_size

let default_page_size : Int

node-slack-sdk's defaultPageSize.

#
home_view

fn home_view(blocks : Array[
LayoutBlock
], callback_id? : String, private_metadata? : String) -> Json

An App Home tab view.

#
interpret_response

The rules, as a free function.

Slack answers a refusal with HTTP 200 and {"ok": false}, so the status code and ok are two different questions: 429 and 5xx are infrastructure, ok: false is Slack declining.

#
merge_params

Merge a paginator's parameters into a caller's, without mutating theirs.

The paginator's values win: a caller who passed limit in the base params AND a page_size meant the page size, and two limit fields on the wire would let Slack pick.
fn modal(title : String, blocks : Array[
LayoutBlock
], submit? : String, close? : String, callback_id? : String, private_metadata? : String) -> Json

A modal view. title and submit are what Slack requires of one.

#
page_items

fn page_items(response :
ApiResponse
, key : String) -> Array[Json]

Pull the items out of a paged response.

Slack has no single name for "the collection": conversations.list answers with channels, users.list with members, conversations.history with messages. So the key is the caller's to supply, and an absent or non-array key yields nothing rather than raising -- a page with no items is a normal thing on the last page of a filtered query.

#
view

fn view(type_ : String, blocks : Array[
LayoutBlock
], title? : String, submit? : String, close? : String, callback_id? : String, private_metadata? : String, external_id? : String, clear_on_close? : Bool, notify_on_close? : Bool) -> Json

Build a view payload from typed blocks.

Views are not blocks and not LayoutBlocks, but the only part of one a caller usually cares about is its block list -- so this assembles the rest.