README

marianoguerra/slack/typed does not have a README file

#
TypedError

pub(all) suberror TypedError {
Slack(
SlackError
)
ResponseShapeError(api_method~ : String, key~ : String)
} derive(
Debug
)

A typed call's failure.
impl Show for TypedError

#
TypedError::code

fn TypedError::code(self : TypedError) -> String

node-slack-sdk's ErrorCode for the wrapped case, and this package's own for the case node has no name for.

#
TypedError::describe_error

fn TypedError::describe_error(self : TypedError) -> String

#
TypedError::slack

The wrapped SlackError, for the cases that actually happen.

ResponseShapeError is the rare one and the wrapping puts it in the way of the common ones, so this is the shortcut: if e.slack() is Some(err) gets back to a rate limit or a missing_scope in one step.

#
Api

pub struct Api {
client :
Client

}

A Client, and the extraction step that turns its answers into @model values.

Holds the client rather than replacing it: Api::client is always there, and mixing the two levels in one function is the expected way to use this.

#
Api::auth_revoke

async fn Api::auth_revoke(self : Api, dry_run? : Bool) -> Bool raise TypedError

auth.revoke, answering whether the token was actually revoked.

dry_run reports what would happen without doing it, which is the whole reason this answers a Bool rather than Unit.

#
Api::auth_test

async fn Api::auth_test(self : Api) -> Identity raise TypedError

auth.test: who this token is. The first call most apps make.

#
Api::bookmarks_add

async fn Api::bookmarks_add(self : Api, channel_id~ : String, title~ : String, type_~ : String, link? : String, emoji? : String, entity_id? : String, parent_id? : String) ->
Bookmark
raise TypedError

bookmarks.add, as the bookmark it created.

#
Api::bookmarks_list

async fn Api::bookmarks_list(self : Api, channel_id~ : String) -> Array[
Bookmark
] raise TypedError

bookmarks.list, which is not paginated.

#
Api::chat_delete

async fn Api::chat_delete(self : Api, channel~ : String, ts~ : String, as_user? : Bool) -> Posted raise TypedError

chat.delete, as what it deleted.

#
Api::chat_delete_scheduled_message

async fn Api::chat_delete_scheduled_message(self : Api, channel~ : String, scheduled_message_id~ : String, as_user? : Bool) -> Unit raise TypedError

chat.deleteScheduledMessage: cancel one before it is sent.
async fn Api::chat_get_permalink(self : Api, channel~ : String, message_ts~ : String) -> String raise TypedError

chat.getPermalink, as the URL.

#
Api::chat_me_message

async fn Api::chat_me_message(self : Api, channel~ : String, text~ : String) -> Posted raise TypedError

chat.meMessage, as where it landed.

#
Api::chat_post_ephemeral

async fn Api::chat_post_ephemeral(self : Api, 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) -> String raise TypedError

chat.postEphemeral, as the ts of the message only that user can see.

A bare ts and not a Posted: an ephemeral message has no channel echoed back and cannot be updated or deleted, so there is nothing else to carry.

#
Api::chat_post_message

async fn Api::chat_post_message(self : Api, 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) -> Posted raise TypedError

chat.postMessage, as where it landed.

Posted.channel is an id and not a Channel, because that is what Slack answers here -- even when the request named the channel by name.

#
Api::chat_schedule_message

async fn Api::chat_schedule_message(self : Api, 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) -> Scheduled raise TypedError

chat.scheduleMessage, as the handle to cancel it with.

#
Api::chat_scheduled_messages_list

async fn Api::chat_scheduled_messages_list(self : Api, channel? : String, cursor? : String, limit? : Int, latest? : String, oldest? : String) -> Page[
ScheduledMessage
] raise TypedError

One page of chat.scheduledMessages.list.

#
Api::chat_unfurl

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

chat.unfurl: attach a preview to a link someone posted.

#
Api::chat_update

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

chat.update, as where the edited message is.

#
Api::client

The low-level client, for everything this package does not wrap.

Not an escape hatch so much as the other half of the API: Client::call reaches every one of Slack's 326 methods, and ApiResponse.raw reaches every field of every response.

#
Api::conversations_archive

async fn Api::conversations_archive(self : Api, channel~ : String) -> Unit raise TypedError

conversations.archive.

#
Api::conversations_close

async fn Api::conversations_close(self : Api, channel~ : String) -> Unit raise TypedError

conversations.close.

#
Api::conversations_create

async fn Api::conversations_create(self : Api, name~ : String, is_private? : Bool) ->
Channel
raise TypedError

conversations.create, as the channel it created.

#
Api::conversations_history

async fn Api::conversations_history(self : Api, channel~ : String, cursor? : String, limit? : Int, latest? : String, oldest? : String, inclusive? : Bool, include_all_metadata? : Bool) -> Page[
Message
] raise TypedError

One page of conversations.history.

#
Api::conversations_history_all

async fn Api::conversations_history_all(self : Api, channel~ : String, latest? : String, oldest? : String, page_size? : Int, max_pages? : Int) -> Array[
Message
] raise TypedError

Every page of conversations.history.

#
Api::conversations_info

async fn Api::conversations_info(self : Api, channel~ : String, include_locale? : Bool, include_num_members? : Bool) ->
Channel
raise TypedError

conversations.info, as a Channel.

#
Api::conversations_invite

async fn Api::conversations_invite(self : Api, channel~ : String, users~ : Array[String], force? : Bool) ->
Channel
raise TypedError

conversations.invite, as the channel with its new members.

#
Api::conversations_join

async fn Api::conversations_join(self : Api, channel~ : String) ->
Channel
raise TypedError

conversations.join, as the channel just joined.

#
Api::conversations_kick

async fn Api::conversations_kick(self : Api, channel~ : String, user~ : String) -> Unit raise TypedError

conversations.kick.

#
Api::conversations_leave

async fn Api::conversations_leave(self : Api, channel~ : String) -> Unit raise TypedError

conversations.leave.

#
Api::conversations_list

async fn Api::conversations_list(self : Api, types? : Array[String], exclude_archived? : Bool, limit? : Int, cursor? : String) -> Page[
Channel
] raise TypedError

One page of conversations.list.

#
Api::conversations_list_all

async fn Api::conversations_list_all(self : Api, types? : Array[String], exclude_archived? : Bool, page_size? : Int, max_pages? : Int) -> Array[
Channel
] raise TypedError

Every page of conversations.list.

max_pages is worth setting: this is a Tier 2 method, and a big workspace will rate-limit a full walk.

#
Api::conversations_mark

async fn Api::conversations_mark(self : Api, channel~ : String, ts~ : String) -> Unit raise TypedError

conversations.mark: move the read cursor.

#
Api::conversations_members

async fn Api::conversations_members(self : Api, channel~ : String, cursor? : String, limit? : Int) -> Page[String] raise TypedError

One page of conversations.members, which is ids rather than users.

The key is members, the same key users.list uses for whole user objects. Two methods, one key name, two types -- which is the argument against a generic extractor, in one line.

#
Api::conversations_members_all

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

Every page of conversations.members.

#
Api::conversations_open

async fn Api::conversations_open(self : Api, channel? : String, users? : Array[String], return_im? : Bool, prevent_creation? : Bool) ->
Channel
raise TypedError

conversations.open, as the DM or MPIM it opened or found.

#
Api::conversations_rename

async fn Api::conversations_rename(self : Api, channel~ : String, name~ : String) ->
Channel
raise TypedError

conversations.rename, as the channel under its new name.

#
Api::conversations_replies

async fn Api::conversations_replies(self : Api, channel~ : String, ts~ : String, cursor? : String, limit? : Int, latest? : String, oldest? : String, inclusive? : Bool) -> Page[
Message
] raise TypedError

One page of conversations.replies: a thread's parent and its replies.

The parent comes back first and carries thread_ts == ts, which Message::is_thread_reply is the way to tell apart.

#
Api::conversations_set_purpose

async fn Api::conversations_set_purpose(self : Api, channel~ : String, purpose~ : String) ->
Channel
raise TypedError

conversations.setPurpose, as the channel with its new purpose.

#
Api::conversations_set_topic

async fn Api::conversations_set_topic(self : Api, channel~ : String, topic~ : String) ->
Channel
raise TypedError

conversations.setTopic, as the channel with its new topic.

#
Api::files_complete_upload_external

async fn Api::files_complete_upload_external(self : Api, files~ : Json, channel_id? : String, initial_comment? : String, thread_ts? : String) -> Array[
File
] raise TypedError

files.completeUploadExternal, as the files it finished.

#
Api::files_delete

async fn Api::files_delete(self : Api, file~ : String) -> Unit raise TypedError

files.delete.

#
Api::files_get_upload_url_external

async fn Api::files_get_upload_url_external(self : Api, filename~ : String, length~ : Int, alt_txt? : String, snippet_type? : String) -> Upload raise TypedError

files.getUploadURLExternal, as where to PUT the bytes.

#
Api::files_info

async fn Api::files_info(self : Api, file~ : String, cursor? : String, limit? : Int) ->
File
raise TypedError

files.info, as a File.

#
Api::files_list

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

files.list, which pages by number rather than by cursor.

Hence an array and not a Page: the paging object it answers with is not the cursor scheme the rest of this file uses, and pretending otherwise would hand back a Page whose cursor was always None.

#
Api::new

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

Build the client and wrap it in one step, with Client::new's arguments.

#
Api::of

Wrap an existing client.

The usual entry point, because a Client is where the transport, the token and the base URL are already configured.

#
Api::pins_add

async fn Api::pins_add(self : Api, channel~ : String, timestamp? : String) -> Unit raise TypedError

pins.add.

#
Api::pins_remove

async fn Api::pins_remove(self : Api, channel~ : String, timestamp? : String) -> Unit raise TypedError

pins.remove.

#
Api::reactions_add

async fn Api::reactions_add(self : Api, channel~ : String, name~ : String, timestamp~ : String) -> Unit raise TypedError

reactions.add.

#
Api::reactions_remove

async fn Api::reactions_remove(self : Api, name~ : String, channel? : String, timestamp? : String, file? : String, file_comment? : String) -> Unit raise TypedError

reactions.remove.

#
Api::team_info

async fn Api::team_info(self : Api, team? : String, domain? : String) ->
Team
raise TypedError

team.info, as a Team.

#
Api::usergroups_create

async fn Api::usergroups_create(self : Api, name~ : String, handle? : String, description? : String, channels? : Array[String], include_count? : Bool) ->
Usergroup
raise TypedError

usergroups.create, as the group it created.

#
Api::usergroups_list

async fn Api::usergroups_list(self : Api, include_disabled? : Bool, include_count? : Bool, include_users? : Bool) -> Array[
Usergroup
] raise TypedError

usergroups.list, which is not paginated.

#
Api::usergroups_users_list

async fn Api::usergroups_users_list(self : Api, usergroup~ : String, include_disabled? : Bool) -> Array[String] raise TypedError

usergroups.users.list, which is ids.

#
Api::usergroups_users_update

async fn Api::usergroups_users_update(self : Api, usergroup~ : String, users~ : Array[String], include_count? : Bool) ->
Usergroup
raise TypedError

usergroups.users.update, as the group with its new membership.

#
Api::users_conversations

async fn Api::users_conversations(self : Api, user? : String, types? : Array[String], exclude_archived? : Bool, cursor? : String, limit? : Int) -> Page[
Channel
] raise TypedError

One page of users.conversations.

#
Api::users_get_presence

async fn Api::users_get_presence(self : Api, user? : String) -> Presence raise TypedError

users.getPresence.

#
Api::users_info

async fn Api::users_info(self : Api, user~ : String, include_locale? : Bool) ->
User
raise TypedError

users.info, as a User.

#
Api::users_list

async fn Api::users_list(self : Api, cursor? : String, limit? : Int, include_locale? : Bool) -> Page[
User
] raise TypedError

One page of users.list.

The members are objects here. On conversations.members the identically named key holds ids.

#
Api::users_list_all

async fn Api::users_list_all(self : Api, include_locale? : Bool, page_size? : Int, max_pages? : Int) -> Array[
User
] raise TypedError

Every page of users.list.

#
Api::users_lookup_by_email

async fn Api::users_lookup_by_email(self : Api, email~ : String) ->
User
raise TypedError

users.lookupByEmail, as a User.

#
Api::users_profile_get

async fn Api::users_profile_get(self : Api, user? : String, include_labels? : Bool) ->
Profile
raise TypedError

users.profile.get, as a Profile.

#
Api::users_profile_set

async fn Api::users_profile_set(self : Api, user? : String, profile? : Json, name? : String, value? : String) ->
Profile
raise TypedError

users.profile.set, answering the profile as stored.

#
Api::users_set_presence

async fn Api::users_set_presence(self : Api, presence~ : String) -> Unit raise TypedError

users.setPresence.

#
Api::views_open

async fn Api::views_open(self : Api, trigger_id~ : String, view~ : Json) ->
View
raise TypedError

views.open, as the view Slack stored.

#
Api::views_publish

async fn Api::views_publish(self : Api, user_id~ : String, view~ : Json, hash? : String) ->
View
raise TypedError

views.publish, as the App Home view Slack stored.

#
Api::views_push

async fn Api::views_push(self : Api, trigger_id~ : String, view~ : Json) ->
View
raise TypedError

views.push, as the view it pushed onto the stack.

#
Api::views_update

async fn Api::views_update(self : Api, view~ : Json, view_id? : String, external_id? : String, hash? : String) ->
View
raise TypedError

views.update, as the view after the update.

#
Identity

pub(all) struct Identity {
url : String
team : String
user : String
team_id : String
user_id : String
bot_id : String?
is_enterprise_install : Bool?
enterprise_id : String?
app_id : String?
app_name : String?
expires_in : Int?
} derive(Eq,
Debug
)

Who a token is: auth.test, which is the first call most apps make.

The five required fields are the ones Slack answers unconditionally for any valid token. bot_id is present for a bot token and absent for a user one, which is the cheapest way to tell them apart.

#
Identity::is_bot

fn Identity::is_bot(self : Identity) -> Bool

Whether this token belongs to a bot.

#
Page

pub(all) struct Page[T] {
items : Array[T]
cursor : String?
response :
ApiResponse

}

One page of a cursor-paginated call.

Carries the whole response as well as the items, because the interesting fields of a page are not all items -- has_more on conversations.history, the warnings on a partial users.list.

#
Page::has_more

fn[T] Page::has_more(self : Page[T]) -> Bool

Whether another page exists.

#
Posted

pub(all) struct Posted {
channel : String
ts : String
message :
Message
?
} derive(Eq,
Debug
)

What chat.postMessage and chat.update answer.

Not a Channel: the channel here is an id, which is the clearest case in the whole API for why extraction cannot be generic.

#
Presence

pub(all) struct Presence {
presence : String
online : Bool?
auto_away : Bool?
manual_away : Bool?
connection_count : Int?
last_activity : Int64?
} derive(Eq,
Debug
)

A user's presence: users.getPresence.

Everything but presence needs the users:read scope on your own user, so the rest is optional and usually absent for anyone else.

#
Scheduled

pub(all) struct Scheduled {
scheduled_message_id : String
channel : String
post_at : Int64
message :
Message
?
} derive(Eq,
Debug
)

A message queued by chat.scheduleMessage.

scheduled_message_id is what chat.deleteScheduledMessage cancels it with, and the only handle you get -- there is no ts until it is sent.

#
Upload

pub(all) struct Upload {
upload_url : String
file_id : String
} derive(Eq,
Debug
)

Where to PUT a file's bytes: files.getUploadURLExternal.

The upload itself is an ordinary HTTP request to upload_url and not a Web API call, so it is not something this library does -- see "Not included" in the library's README. file_id is what files.completeUploadExternal finishes with.

#
to_typed_error

fn to_typed_error(e : Error) -> TypedError

Narrow an arbitrary Error to a TypedError.

Variant patterns are the only way to match an error value and they are only in scope in the package that declares them, so a caller outside this one cannot take a TypedError apart from an Error without this. The same shape as @api.to_slack_error, which it delegates to.