{"id":13747478,"url":"https://github.com/jejacks0n/bitbot","last_synced_at":"2025-08-16T16:09:30.942Z","repository":{"id":24288878,"uuid":"27683833","full_name":"jejacks0n/bitbot","owner":"jejacks0n","description":"Bitbot: Rack based Slack bot with a responder DSL and support for Wit.ai natural language processing.","archived":false,"fork":false,"pushed_at":"2022-02-17T06:38:29.000Z","size":67,"stargazers_count":12,"open_issues_count":7,"forks_count":4,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-07-21T07:31:41.612Z","etag":null,"topics":["rack","rails","ruby","slack","wit"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jejacks0n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-07T20:36:24.000Z","updated_at":"2023-12-07T22:49:18.000Z","dependencies_parsed_at":"2022-07-10T11:00:19.448Z","dependency_job_id":null,"html_url":"https://github.com/jejacks0n/bitbot","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jejacks0n/bitbot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jejacks0n%2Fbitbot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jejacks0n%2Fbitbot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jejacks0n%2Fbitbot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jejacks0n%2Fbitbot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jejacks0n","download_url":"https://codeload.github.com/jejacks0n/bitbot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jejacks0n%2Fbitbot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270735259,"owners_count":24636329,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-16T02:00:11.002Z","response_time":91,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["rack","rails","ruby","slack","wit"],"created_at":"2024-08-03T06:01:30.585Z","updated_at":"2025-08-16T16:09:30.913Z","avatar_url":"https://github.com/jejacks0n.png","language":"Ruby","readme":"# Bitbot\n\n[![Gem Version](https://img.shields.io/gem/v/bitbot.svg)](http://badge.fury.io/rb/bitbot)\n[![Build Status](https://img.shields.io/travis/jejacks0n/bitbot.svg)](https://travis-ci.org/jejacks0n/bitbot)\n[![Maintainability](https://api.codeclimate.com/v1/badges/7e22d47bd547a055c63e/maintainability)](https://codeclimate.com/github/jejacks0n/bitbot/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/7e22d47bd547a055c63e/test_coverage)](https://codeclimate.com/github/jejacks0n/bitbot/test_coverage)\n[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)\n\nBitbot is a lightweight Rack endpoint specifically intended for Slack webhooks. It can be mounted within a Rails app, or\ncan be run as a standalone Rack app with the `config.ru` provided as an example.\n\nYou can write custom responders that take advantage of the logic within your larger application. Responders have support\nfor custom routing and can utilize [Wit.ai](http://wit.ai) natural language processing.\n\nFor more complex responder examples, check out the [bitbot-responders](https://github.com/modeset/bitbot-responders)\nproject.\n\n## Installation\n\n```ruby\ngem \"bitbot\", github: \"jejacks0n/bitbot\"\n```\n\n### Rails\n\nBitbot can run fine without Rails, but if you're using Rails, you can run the install generator. The generator will\nprovide an initializer and mount the rack app within your routes -- be sure to update both the initializer and route if\nyou change where it's mounted.\n\n```shell\nrails generate bitbot:install\n```\n\n## Configuration\n\nBitbot requires being configured, but to simplify the README it's not included here, please check the\n[config.ru](https://github.com/modeset/bitbot/blob/master/config.ru) for an example and configuration documentation.\n\nThe `config.ru` file is provided as a convenience and only serves as an example -- it is not included with the gem.\n\nYou can grab the `config.ru` and run the listener with `rackup`. Or if you've installed the generator, you can test your\nsetup by starting your rails server and running (based on your configuration and port):\n\n```shell\ncurl --data 'text=help+me\u0026user_name=tester\u0026channel=none\u0026token=token' \\\nhttp://localhost:9292/rack-bitbot-webhook\n```\n\nYou should get a JSON response back. If you don't, Bitbot is intentionally vague about what could've gone wrong, but the\nlikely causes are that the token isn't correct, the request isn't a post, or that the username was the same as the bots\n(she doesn't respond to herself).\n\n## Setting up Slack\n\nTo get all of the configuration tokens and urls, you'll need to go to Slack and add the Incoming Webhooks, and Outgoing\nWebhooks integrations. You can get your incoming url, and outgoing token by doing this, which you can then set as\nenvironment variables and load them into your configuration.\n\nWhen setting up the Outgoing Webhook integration you will need to know where you have configured the Rack endpoint so\nyou can provide that as the url that will be used.\n\n## Adding Responders\n\nThere's a basic DSL for creating responders, which allows you to register help for the various commands, and define\nresponder routes. Bitbot considers commands to be \"routable\", and so you can define them using `route`. Here's an\nexample responder that specifies `category`, `help` and a single `route`. The `category` indicates grouping within the\ndefault help responder, but is somewhat arbitrary in it's meaning should you do something else with it.\n\n```ruby\nclass MyResponder \u003c Bitbot::Responder\n  category \"Greetings\"\n  help \"hi bot\", description: \"I'll respond with a greeting\"\n\n  route :say_hi_back, /^hi bot/i do\n    respond_with(\"awesome! hi #{message.user_name}.\")\n  end\nend\n```\n\nA route must be named, and provide a regexp matcher. Here's another example, but here we capture a value from the\nmessage.\n\nIn general a responder route will return a hash that's then sent back to the Slack request but additional messages can\nbe announced from within the responder. As a general rule you should always use the `respond_with` method in your\nresponder routes because it can determine if it should return the Hash, or make the announcement itself. You can also\nuse the `private_message`, or `public_message` helper methods, which always announce and don't return a Hash.\n\n```ruby\nroute :echo, /^echo (.*)/i do |string|\n  respond_with(\"heard #{message.user_name} say \\\"#{string}\\\" in #{message.channel}.\")\nend\n```\n\n### Confirmations\n\nConfirmations are included as a base feature, but need redis to work. Provide your own redis connection in the\nconfiguration and you can add confirmations (and more) to your responders. By default the configuration assumes redis is\nrunning locally, and is available at Redis.current -- otherwise it will try to connect to redis at the standard port.\n\n```ruby\nroute :say_hi_back?, /^hi bot/i do\n  confirm(\"were you saying hi to me?\", \"yes\") do\n    respond_with(\"awesome! hi #{message.user_name}.\")\n  end\nend\n```\n\n### Wit.ai\n\nWe think [Wit.ai](http://wit.ai) is pretty rad for a bot setup, but it does take some work to get it trained and working\nthe way you want. This is part of the fun, and part of the challenge.\n\nTo use Wit.ai in your responders, you need to require `wit_ruby` and include the Wit module in your responder. Then you\ncan define intents, and which route they go to, as well as any entities that are within them. In the most complex form\nthis would look something like the following.\n\n**Note:** wit_ruby expects `ENV[\"WIT_AI_TOKEN\"]` to be defined. [read more](https://github.com/gching/wit_ruby)\n\n```ruby\nclass MyResponder \u003c Bitbot::Responder\n  include Bitbot::Responder::Wit\n  category \"Greetings\"\n  help \"hi bot my name is \u003cname\u003e\", description: \"I'll respond with a greeting\"\n\n  intent \"greeting\", :say_hi_back, entities: { contact: -\u003e(e) { e['value'] } }\n  route :say_hi_back, /^hi bot, my name is (.*)/i do |specified_name|\n    respond_with(\"awesome! hi #{specified_name}, I'm bot.\")\n  end\nend\n```\n\nNow if you train Wit to understand \"Hello, I'm Jeremy Jackson\", including the name portion as a `wit/contact` entity, it\nwill make it through to the responder as the `specified_name` argument to the block. Again, this is a complex thing to\nsetup and train, so have fun with it. You may also note that the route has a fallback regexp that allows using directly,\neven if Wit.ai wasn't able to determine what the intent was.\n\nWorth mentioning, the proc that you see in the `entities` above doesn't need to be specified if all you want is the\nvalue, but if it's a proc it will call the proc with the entity hash. Some entities have complex structures, like\n`duration`, where you may want to pull out the seconds, instead of the number of minutes or hours that may have been\nprovided. In those cases use `duration: -\u003e(e) { e['normalized']['value'] }`, but in our above example, we could've just\nused `contact: nil` and the value would be pulled automatically for us.\n\n## Announcing\n\nYou can announce any message into any channel on Slack using the bot, for instance in a background job to have something\nhappen on an action or predefined schedule. You must configure Bitbot's `webhook_url` by setting up an Incoming Webhook\nIntegration on Slack before this will work however.\n\n```ruby\nBitbot.announce(text: \"Hello all!\", channel: \"#general\")\n```\n\nYou can send private messages if you like as well.\n\n```ruby\nBitbot.announce(text: \"Hello you!\", channel: \"@username\")\n```\n\nYou can also reuse any of the existing responder routes by having the responder handle the route directly. Obviously in\nthese cases you must provide anything that that the might expect from the message, which always includes `text`,\nand may include common things like `channel` or `user_name`. Since responder routes can be pretty vague, and implement\nany number of things, you may have to provide additional information as well.\n\nSince responders can make their own announcements, or return a hash you can use the `Bitbot.announce` method based on\nconfiguration.\n\n```ruby\nBitbot.announce(MyResponder.new.respond_to(text: \"Hi bot\", channel: \"#general\", user_name: \"system\"))\n# or\nMyResponder.new.respond_to(text: \"Hi bot\", channel: \"#general\", user_name: \"system\")\n```\n\nRegex can get hairy, so the `respond_to` method also accepts a block to return any additional context you may want to use inside your route.\n\n```ruby\nMyResponder.new.respond_to(text: \"Archive user\", channel: \"#admin\", user_name: \"system\") { { id: 2 } }\n\nroute :archive, /^archive user/i do\n  # access info from blockk\n  more_info = context_block.call\n  # do something with the info\n  User.find(more_info[:id]).archive\n  respond_with(\"You got it, User with id: #{more_info[:id]} has been archived.\")\nend\n```\n\n## License\n\nLicensed under the [MIT License](http://creativecommons.org/licenses/MIT/)\n\nCopyright 2019 [jejacks0n](https://github.com/jejacks0n)\n\n## Make Code Not War\n\n```\n\n```\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjejacks0n%2Fbitbot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjejacks0n%2Fbitbot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjejacks0n%2Fbitbot/lists"}