Crystal client for building Slack apps and tools using the Slack API.
-
Add the dependency to your
shard.yml
:dependencies: slack: github: the-business-factory/slack.cr
-
Run
shards install
A demo app is published at https://github.com/the-business-factory/hirobot.app.
Slack.configure do |config|
config.bot_scopes = ["incoming-webhook"] # Array(String)
config.client_id = ENV["SLACK_CLIENT_ID"] # String
config.client_secret = ENV["SLACK_CLIENT_SECRET"] # String
config.signing_secret = ENV["SLACK_SIGNING_SECRET"] # String
config.signing_secret_version = "v0" # String
config.webhook_delivery_time_limit = 5.minutes # Time::Span
end
# Most apps will want to have OAuth enabled for installation.
Slack::AuthHandler.configure do |config|
config.oauth_redirect_url = ENV["OAUTH_REDIRECT_URL"]
end
# To enable "Sign in with Slack," you'll need to configure
# Slack's OpenID Connecion handling.
Slack::SignIn.configure do |config|
config.sign_in_redirect_url = ENV["SIGN_IN_REDIRECT_URL"]
end
require "slack"
def process_webhook(request : HTTP::Request)
event_payload = Slack.process_webhook(event)
case event_payload
when .is_a?(Slack::UrlVerification)
json(event_payload.response.to_json)
else
handle_event(event_payload.event)
end
end
# You can easily handle only the events you expect back, with type safety.
def handle_event(event : Slack::Event::Message::MessageChanged)
pp event.message.text
end
# And of course sometimes, you just want to ignore things you don't expect.
def handle_event(unhandled_event)
end
When returning responses from the Slack API, error responses are raised, rather than returned as separate error objects. This provides strongly typed responses for the majority of API traffic; Slack::Api::Error errors can be rescued to allow customized error handling if needed.
class ExampleSlackApiCall
def initialize(@token : String, @channel_id : String)
end
def run
# Guaranteed to be some sort of Slack::Model::Conversation object.
channel = Slack::Api::ConversationsInfo.new(token, channel_id).call
# Now you can with Slack's polymorphic API in uniform ways.
case channel
when Slack::Models::IMChat
Log.info { "IM Chat Latest Message Read: #{channel.latest}" }
when Slack::Models::PublicChannel
Log.info { "Public Team Channel Name: #{channel.name}" }
end
rescue exc : Slack::Api::Error
# exc.message will typically have the JSON Error Results from Slack's API.
Log.info { "Error Raised: #{exc.message}" }
end
end
# Users can easily define custom UI components to help build out "app specific"
# "UI Kits" fairly easily, focusing on the UX and business logic rather than
# the stupid internals of Slack's API.
struct ButtonSection < Slack::UI::CustomComponent
include Slack::UI::BaseComponents
def self.render(action_id : String)
buttons = %w(Submit Cancel).map do |text|
style = text == "Submit" ? ButtonStyles::Primary : ButtonStyles::Danger
ButtonElement.render(
action_id: "#{action_id}_#{text.downcase}",
button_text: text,
style: style
)
end
Slack::UI::Blocks::Actions.new elements: buttons
end
end
class SlackLinkPage < WebhookAction
include Slack::UI::BaseComponents
post "/slack/links" do
command = Slack.process_command(request)
text = command.text.presence || "nothing"
text_section = TextSection.render(
text: "processed #{command.command} with #{text} as text."
)
input_element = InputElement.render(
action_id: "compensation",
placeholder_text: "e.g. $120,000-$190,000",
label_text: "Compensation",
initial_value: ""
)
button_section = ButtonSection.render(
action_id: "button_group_#{Random::Secure.hex}"
)
json({blocks: [text_section, input_element, button_section]})
end
end
- Fork it (https://github.com/the-business-factory/slack.cr/fork)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
- Rob Cole - creator and maintainer
- Alex Piechowski - maintainer