Skip to content

matyus/slackened

Repository files navigation

Slackened

Gem Version

Dependencies

Getting started

  1. Add slackened to your Gemfile

    gem 'slackened'
  2. Configure the Webhook URL in an initializer

    Slackened.configure do |config|
      config.webhook_url = ENV.fetch('SLACK_WEBHOOK_URL') { puts 'SLACK_WEBHOOK_URL is missing.' }
    end
  3. Build a layout

    class PaymentFailedMessage < Slackened::Surface::Message
      def self.layout(payment_id:, context:)
        build do |message|
          message.row header('Payment failed!')
    
          message.row context(context)
    
          message.row section("Please do something about this: #{payment_id}")
    
          # NOTE:
          # if you want/need to design singular blocks via BlockKit builder
          # then use the `custom` method:
    
          message.row custom({
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "Retry the batch process"
            },
            "accessory": {
              "type": "button",
              "text": {
                "type": "plain_text",
                "text": "Retry",
                "emoji": true
              }
            }
          })
        end
      end
    end
  4. Supply the variables

    class ExampleService
      def self.call
        # Calling .post WILL NOT raise an Error
        response = ExampleMessage.post(
          context: Rails.env,
          payment_id: 'payment-abc-erf-123'
        )
    
        puts response.body
    
        # Calling .post! WILL raise an Error
        begin
          ExampleMessage.post!(
            context: Rails.env,
            payment_id: 'payment-abc-erf-123'
          )
        rescue Slackened::Error
          puts "Fail!"
        end
      end
    end

Interactivity

  1. Enable Interactivity & Shortcuts for your app

    https://api.slack.com/apps/YOUR-APP-ID/interactive-messages
    
  2. Set the signing_secret in an initializer

    Slackened.configure do |config|
      config.webhook_url = ENV.fetch('SLACK_WEBHOOK_URL') { puts 'SLACK_WEBHOOK_URL is missing.' }
      config.signing_secret = ENV.fetch('SLACK_SIGNING_SECRET') { puts 'SLACK_SIGNING_SECRET is missing.' }
    end
  3. Validate that the request is real & handle the response

    class ExampleController < ApplicationController
      before_action :validate_request
    
      def response
        # Handle the request
        # https://api.slack.com/interactivity/handling#message_responses
        payload = JSON.parse(params.fetch(:payload))
        response_url = payload['response_url']
    
        # See the Getting Started section above for setting up a Message
        # you can override the default URL via the `post` method here...
        ExampleResponseMessage.post(
          message: 'Message received!',
          user_id: payload.dig('user', 'id'),
          url: payload['response_url']
        )
    
        render plain: :ok
      end
    
      private
    
      def validate_request
        # https://api.slack.com/authentication/verifying-requests-from-slack
        authentic = Slackened::Authentication.validate_request(
          timestamp: request.headers.fetch('X-Slack-Request-Timestamp'),
          signature: request.headers.fetch('X-Slack-Signature'),
          body: request.raw_post
        )
    
        render(plain: 'not ok', head: :unauthorized) and return unless authentic
      end
    end

Blocks

Usable components:

  • Actions

  • Button

    button(
      plain_text: 'Click here',
      action_id: 'foo-1',
      value: 'foo-bar'
    )
  • Context

    context("#{Rails.env} | 2024-12-30")
  • Custom

    This is not a BlockKit component, it lets you pass in a single valid block via the BlockKit builder

    custom({
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "Retry the batch process"
      },
      "accessory": {
        "type": "button",
        "text": {
          "type": "plain_text",
          "text": "Retry",
          "emoji": true
        }
      }
    })
  • Divider

    divider
  • Header

    header('Hello world!')
  • Section

    section('Passing in a single string here creates a single column section')
    section(
      'Passing in multiple strings',
      'will create a two column section',
      'and you are allowed up to ten params',
      'they must all be strings'
    )
  • Text

    text('You may not need to use this directly, actually.')

Surfaces

  • Message

Security

  • Authenticate responses from Slack

TODO

Development

  1. Clone this repo

  2. Install the libraries

    bundle install

About

Interact with your Slack app

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •  

Languages