{"id":20724506,"url":"https://github.com/laserdisc-io/slack4s","last_synced_at":"2026-02-20T17:01:14.292Z","repository":{"id":39718283,"uuid":"401361882","full_name":"laserdisc-io/slack4s","owner":"laserdisc-io","description":"A functional scala library for easily constructing slack bots","archived":false,"fork":false,"pushed_at":"2025-03-14T19:33:45.000Z","size":117,"stargazers_count":5,"open_issues_count":5,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-23T18:05:01.903Z","etag":null,"topics":["hacktoberfest","scala","slack"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/laserdisc-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-08-30T13:54:41.000Z","updated_at":"2025-03-14T19:33:28.000Z","dependencies_parsed_at":"2024-11-26T22:25:15.704Z","dependency_job_id":"4fc15ece-0e29-4dde-87d4-97d21f00c676","html_url":"https://github.com/laserdisc-io/slack4s","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/laserdisc-io/slack4s","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Fslack4s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Fslack4s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Fslack4s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Fslack4s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/laserdisc-io","download_url":"https://codeload.github.com/laserdisc-io/slack4s/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Fslack4s/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29658167,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T16:33:43.953Z","status":"ssl_error","status_checked_at":"2026-02-20T16:33:43.598Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","scala","slack"],"created_at":"2024-11-17T04:15:02.417Z","updated_at":"2026-02-20T17:01:14.192Z","avatar_url":"https://github.com/laserdisc-io.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# slack4s\n\n![CI](https://github.com/laserdisc-io/slack4s/actions/workflows/ci.yaml/badge.svg) \n[![codecov](https://codecov.io/gh/laserdisc-io/slack4s/branch/main/graph/badge.svg?token=BEDHQ818EI)](https://codecov.io/gh/laserdisc-io/slack4s)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/laserdisc-io/slack4s)](https://github.com/laserdisc-io/slack4s/releases)\n\nA pure functional library for easily building slack bots, built on [cats 3.x](https://typelevel.org/cats/), [http4s](https://http4s.org/) and the [Slack Java SDK](https://github.com/slackapi/java-slack-sdk/).  \n\nRight now, [slash commands](https://api.slack.com/interactivity/slash-commands) are supported (contributions welcome!).   This library takes care of \n\n* Interacting with Slack's API\n* Encoding/decoding payloads\n* Verifying signature validity\n* Handling background callbacks for longer running commands\n\nSimply provide your business logic and you've got a deployable app!\n\n## Example\n* See [SpaceNewsExample](src/test/scala/examples/SpaceNewsExample.scala) for a working example of a slash command handler.\n\n## Tutorial\n* See [docs/tutorial.md](docs/tutorial.md) for a walk-through of configuring and running [SpaceNewsExample](src/test/scala/examples/SpaceNewsExample.scala). \n\n## Quickstart\n\nAdd the following dependency:\n\n```sbt\nlibraryDependencies += \"io.laserdisc\" %% \"slack4s\" % latestVersion\n```\n\nIn this example, our [slash command](https://api.slack.com/interactivity/slash-commands) handler will take the form of a persistent HTTP service.  \n\nWith your [signing secret](https://api.slack.com/authentication/verifying-requests-from-slack#about) in hand, getting a skeleton handler up and running is as simple as:\n\n```scala\nimport cats.effect.{IO, IOApp}\nimport io.laserdisc.slack4s.slashcmd.*\n\nobject MySlackBot extends IOApp.Simple {\n\n  val secret: SigningSecret = SigningSecret.unsafeFrom(\"your-signing-secret\") // demo purposes - please don't hardcode secrets  \n  \n  override def run: IO[Unit] = SlashCommandBotBuilder[IO](secret).serve\n\n}\n\n```\n\nSet your slash command's **Request URL** to \n\n```\nhttps://{your-base-url}/slack/slashCmd\n```\n\n\nIssue your slash command, e.g. `/slack4s foo` and you should get the default response:\n\n![default response screenshot with placeholder message](https://user-images.githubusercontent.com/885049/133712091-82037415-8f72-4fcf-b1ae-4942c4f47f95.png)\n\nThe builder has some more useful functions if you need to customize your deployment further:\n\n```scala\nSlashCommandBotBuilder[IO](secret)\n  .withCommandMapper(testCommandMapper)                   // your mapper impl, see next section\n  .withBindOptions(port = 9999, address = \"192.168.0.1\")  // by default, binds to 0.0.0.0:8080\n  .withHttp4sBuilder{                                    \n    // offer the chance to customize http4s' BlazeServerBuilder used under the hood \n    // USE WITH CAUTION; it overrides any settings set by slack4s     \n    _.withIdleTimeout(10.seconds)\n     .withMaxConnections(512)\n  }\n  .serve\n```\n\nIf your container runtime (e.g. k8s, AWS ECS) needs a health check endpoint, use: \n\n```\nhttps://{your-base-url}/healthCheck\n```\n\n## Implementing Your Mapper Logic\n\nCreate an implementation of `CommandMapper[F]` and pass it to the builder as follows e.g.:\n\n```scala\n\nval myMapper: CommandMapper[F] = .. // see the next section\n\nSlashCommandBotBuilder[IO](secret)\n  .withCommandMapper(myMapper)\n  .serve\n```\n\n`CommandMapper[F]` is a type alias for: \n\n```scala\nSlashCommandPayload =\u003e F[Command[F]]\n```\n\nYour implementation of this effect defines your business logic.  The input is the slash command request from Slack. The output defines how to respond to that request.\n\nSlack4s will only evaluate this effect if the incoming request's slack signature has been validated against your signing secret.\n\n### `SlashCommandPayload`\n \n* This [Java class provided by Slack's Java SDK](https://github.com/slackapi/java-slack-sdk/blob/main/slack-app-backend/src/main/java/com/slack/api/app_backend/slash_commands/payload/SlashCommandPayload.java) (a dependency of this library) models the incoming request.\n* Of primary interest is the `text` field, containing the arguments to you `/command` as provided by the user.\n* Other fields provide contextual information about the call, such as `userId`, `channelName`, etc.\n\n:warning: Slack4s' validation of the request signature only proves that the request originated from slack.  You still need to apply your own level of (dis)trust to the `text` value, as it comes verbatim from the user.  \n\nNot only should you sanitize this input appropriately, you'll also have to handle/strip any formatting it contains.  Slack users tend to copy and paste slack text into commands - don't be surprised to get formatted input, e.g. `*homer simpson*` instead of `homer simpson`.\n\n### `Command[F]`    \n\nThis is the description of how - _and when_ - to handle the user's request. The scaladoc on [Command[F]](src/main/scala/io/laserdisc/slack4s/slashcmd/Models.scala) should have all the information you need, but at a high level, It defines the following fields:\n\n* **handler**: `F[ChatPostMessageRequest]`  \n   * The effect to evaluate in response to the input.\n   * [ChatPostMessageRequest](https://github.com/slackapi/java-slack-sdk/blob/main/slack-api-client/src/main/java/com/slack/api/methods/request/chat/ChatPostMessageRequest.java) is the Slack API Java model representing the response message. \n      * Importing `io.laserdisc.slack4s.slack._` gives you a bunch of convenience functions to build this reponse object (e.g. `slackMessage(...)`, `markdownWithImgSection(...)`, etc.)\n      * You can explore with the possible response structures by playing with the excellent [Slack Block Kit Builder](https://api.slack.com/tools/block-kit-builder).\n* **responseType**: `ResponseType`\n   * Whether to respond immediately, or process the information in a background queue and [post to a callback URL](https://api.slack.com/interactivity/slash-commands#responding_to_commands).  \n   * See the [scaladoc for ResponseType](src/main/scala/io/laserdisc/slack4s/slashcmd/Models.scala) for all the options here.\n* **logId**: `LogToken` \n  * `\"NA\"` by default, this token used in slack4s's logs when processing this particular command (useful for log filtering)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaserdisc-io%2Fslack4s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaserdisc-io%2Fslack4s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaserdisc-io%2Fslack4s/lists"}