{"id":13507544,"url":"https://github.com/techgaun/ex_mustang","last_synced_at":"2025-07-10T10:39:34.783Z","repository":{"id":62429211,"uuid":"65775721","full_name":"techgaun/ex_mustang","owner":"techgaun","description":":sparkles: A simple, clueless bot","archived":false,"fork":false,"pushed_at":"2020-10-08T05:23:42.000Z","size":583,"stargazers_count":70,"open_issues_count":27,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-04-14T06:05:25.287Z","etag":null,"topics":["bot","elixir","hacktoberfest","responder","slack","slack-bot","standup-reminder","uptime-check","uptime-monitoring"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/techgaun.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-08-16T01:03:41.000Z","updated_at":"2024-04-12T12:08:24.000Z","dependencies_parsed_at":"2022-11-01T20:06:13.007Z","dependency_job_id":null,"html_url":"https://github.com/techgaun/ex_mustang","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techgaun%2Fex_mustang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techgaun%2Fex_mustang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techgaun%2Fex_mustang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techgaun%2Fex_mustang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/techgaun","download_url":"https://codeload.github.com/techgaun/ex_mustang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248565021,"owners_count":21125414,"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","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":["bot","elixir","hacktoberfest","responder","slack","slack-bot","standup-reminder","uptime-check","uptime-monitoring"],"created_at":"2024-08-01T02:00:35.966Z","updated_at":"2025-04-12T11:52:19.881Z","avatar_url":"https://github.com/techgaun.png","language":"Elixir","funding_links":[],"categories":["Chatting","Open Source Bots","Uncategorized"],"sub_categories":["Uncategorized"],"readme":"# ex_mustang\n\n\u003e A simple, clueless bot\n\n![Mustang](images/mustang.jpg)\n\nExMustang is a bot for Slack written in Elixir. While ExMustang is written for Slack, the responder modules should work fine with other Hedwig adapters as well. If you like Mustang, please use [Mustang](images/mustang.jpg) as bot image if possible :)\n\n_Warning: This is a work in progress._\n\n![Example](images/example.png)\n\n![Example](images/example2.png)\n\n![Example](images/example3.png)\n\n### Setup\n\nCreate a Slack bot user from [here](https://my.slack.com/services/new/bot). You will receive an API token you can use. Set the `SLACK_API_TOKEN` environment variable and you should be good to go.\n\nYou can run this bot as below:\n\n```shell\nexport SLACK_API_TOKEN=\"\u003cSLACK_API_TOKEN\u003e\"\nmix run --no-halt\n```\n\nA sample runner configuration looks like below:\n\n```shell\nexport SLACK_API_TOKEN=\"\u003cSLACK_API_TOKEN\u003c\"\nexport GITHUB_TOKEN=\"\u003cGITHUB_TOKEN\u003e\"\nexport GOOGLE_API_KEY=\"\u003cGOOGLE_API_KEY\u003e\"\nexport GIPHY_API_KEY=\"\u003cGIPHY_API_KEY\u003e\"\nexport STANDUP_CHANNEL=\"scrum\"\nexport GH_CHANNEL=\"github\"\nexport PWN_CHANNEL=\"critical\"\nexport UPTIME_CHANNEL=\"critical\"\nexport SLACK_INVITEALL_TOKEN=\"\u003cSLACK_INVITEALL_TOKEN\u003e\"\n\nmix run --no-halt\n```\n\nFor using `ex_mustang` with multiple slack teams, you can use `MIX_ENV` by creating config files such as `yourteam.exs`\nand run as `MIX_ENV=yourteam mix run --no-halt`\n\n### Scheduled Notifications\n\n#### Github Pull Requests Watcher\n\nYou can configure github token by setting `GITHUB_TOKEN`. Also, you can pass list of repos to watch by updating [config](config/config.exs#L11-L17). There are bunch of other stuffs you can configure such as schedule (which follows cron format), slack channel and thresholds.\n\n#### Standup Reminder\n\nThe standup reminder reminds us when its standup time. Our nature is that we either forget track of time or are too lazy to remember about it. This does not make you better at attending standup but is more of a satire for us. You can configure message and other bunch of stuffs on [config](config/config.exs#L5-L9)\n\n#### Have I Been Pwned Checker\n\nThe hibp checker can check list of accounts against [haveibeenpwned.com](https://haveibeenpwned.com)\nby using [ExPwned](https://github.com/techgaun/ex_pwned). You can set the appropriate configuration on config.exs.\n\n```elixir\n# config below runs hibp check once a day and posts if any found breach to configured slack channel\nconfig :ex_mustang, ExMustang.Responders.Pwned,\n  schedule: \"0 * */1 * *\",\n  enabled: true,\n  accounts: [\n    \"abc@example.com\",\n    \"def@example.com\"\n  ],\n  slack_channel: System.get_env(\"PWN_CHANNEL\") || \"general\"\n```\n\n#### Uptime Monitoring\n\nExMustang supports simple uptime monitoring and can perform periodic uptime checks against given set of endpoints.\nThe config block looks like below:\n\n```elixir\nconfig :ex_mustang, ExMustang.Responders.Uptime,\n  schedule: \"*/5 * * *\",\n  enabled: true,\n  endpoints: [\n    [\n      uri: \"https://api.brighterlink.io/status\", status_code: 200, content: ~s(\"msg\":\"ok\"), method: \"GET\",\n      content_type: \"application/json\", req_headers: [{\"User-Agent\", \"ExMustang\"}], timeout: 20_000\n    ]\n  ],\n  slack_channel: System.get_env(\"UPTIME_CHANNEL\") || \"general\"\n```\n\nThe `endpoints` section is where you define the endpoints you're willing to perform uptime check against.\n\n- `uri` - the endpoint to hit\n- `status_code` - expected status code\n- `content` - expected response body content (supports both string and regular expression)\n- `method` - one of `GET`, `POST`, `PUT`, `PATCH` and `DELETE`\n- `body` - body to send as part of `POST`, `PUT` or `PATCH` requests\n- `content_type` - expected content type header value\n- `req_headers` - list of tuples of request headers to send\n- `timeout` - maximum timeout before request fails\n\n#### Random Quote of the Day\n\nExMustang can send a quote as specified in schedule. You can configure schedule from config.exs\nand you can specify `QUOTE_CHANNEL` env-var. If `QUOTE_CHANNEL` is not specified, the quotes are\nsent to `general` channel by default.\n\n### Responders\n\nCurrently, there are following responders and these should ideally work with any Hedwig adapters:\n\n- `ExMustang.Responders.GMap` - gives you google maps search result for your search queries.\n- `ExMustang.Responders.Pwned` -\n- `ExMustang.Responders.Quote` - gives you random funny quote\n- `ExMustang.Responders.Slap` - slaps another user\n- `ExMustang.Responders.Time` - gives time on given timezone (without timezone, uses local timezone of machine ExMustang is running on)\n- `ExMustang.Responders.TimeConvert` - converts given unix timestamp to ISO8601 format\n- `ExMustang.Responders.EncodeDecode` - encoding/decoding tools\n- `ExMustang.Responders.Isup` - checks if a site is up or not via isitup.org API\n- `ExMustang.Responders.RandomInsult` - insults a user with random insults from randominsults.net\n- `ExMustang.Responders.HTTPCat` - gets a cat for corresponding http status code\n- `ExMustang.Responders.Howdoi` - tries to find answer for programming questions\n- `ExMustang.Responders.CommitMsg` - Get random commit messages from http://whatthecommit.com/index.txt\n- `ExMustang.Responders.CLIFu` - Gets clifu gems from http://www.commandlinefu.com\n- `ExMustang.Responders.Whois` - performs a whois query using https://dnsquery.org\n- `ExMustang.Responders.GitTip` - get a random git tip (with support for keywords)\n- `ExMustang.Responders.Birthday` - send a happy birthday to the mentioned user\n- `ExMustang.Responders.InviteAll` - invite all members (of optionally given channel)\n- `ExMustang.Responders.UrbanDictionary` - presents urban dictionary word of the day\n- `ExMustang.Responders.Giphy` - renders gif using https://giphy.com\n\nFor Google Maps search, you have to set `GOOGLE_API_KEY` which has access to call google places api.\n\n```shell\nmustang help - Displays all of the help commands that mustang knows about.\nmustang help \u003cquery\u003e - Displays all help commands that match \u003cquery\u003e.\ngmap \u003csearch_term\u003e - Replies with the information from google places/maps.\npwned \u003csearch_account\u003e - Checks to see if an account has been breached or not\nquote - Replies with a random quote.\nslap - Slaps the user. Format: slap \u003cusername\u003e | me\ntime - get time in a given timezone\nunix2iso \u003cunix_timestamp\u003e - Converts given unix timestamp to ISO format (Auto-replies for values that look like timestamps)\nb64encode \u003ccontent\u003e - base64 encoding of given text content\nb64decode \u003ccontent\u003e - base64 decoding of given text content\nisitup \u003cdomain\u003e - checks if given domain is up or not\ninsult me|\u003cusername\u003e - insults given username with random insults\nhttpcat \u003cstatus_code\u003e - get http status code cat for given value\nhowdoi \u003cquery\u003e - tries to find solution on the given query\ncommitmsg - get a random commit message\nclifu [search_word] - get clifu gem (gives random clifu if no keyword is passed)\nwhois \u003cdomain\u003e - gives whois query for given domain\ngittip [keyword] - Get a random git tip for given keyword\nhappy birthday \u003cme|@user\u003e - Send happy birthday message to the user mentioned\nhdeploy \u003capp-name\u003e - Deploys configured branch to the given app\ninviteall [src_channel] - invite all the members of source channel\ngiphy [search_term] - Tries to find a GIF matching search_term (gives random gif if no search_term is provided)\n```\n\n#### Heroku Deployment\n\nFor heroku deployment to work, you need to specify the following configurations:\n\n- `HEROKU_GITHUB_TOKEN` or `GITHUB_TOKEN`\n- `HEROKU_TOKEN` which is an API key you can get from [here](https://dashboard.heroku.com/account)\n- mapping of apps in your config which is a tuple of heroku app name and map of repo and branch\n\nAn example config looks like below:\n\n```elixir\nconfig :ex_mustang, ExMustang.Responders.HerokuDeploy,\n  github_token: System.get_env(\"HEROKU_GITHUB_TOKEN\") || System.get_env(\"GITHUB_TOKEN\"),\n  token: System.get_env(\"HEROKU_TOKEN\"),\n  apps: [\n    {\"casa-core-stage\", %{repo: \"casaiq/core\", branch: \"master\"}}\n  ]\n```\n\n#### InviteAll Responder\n\nThe invite all responder requires you to provide a token of a non-bot and non-guest slack team member because thats how the slack api works. You can get your personal tokens from [HERE](https://api.slack.com/custom-integrations/legacy-tokens)\n\n### Changelog\n\nThe detail changelog is available [HERE](CHANGELOG.md)\n\n### About Mustang\n\nMustang (pronounced like `moostang` not like the `Ford Mustang`; I don't know phonetics) is my best friend whom I had to leave back in Nepal. After surviving [April 2015 Earthquake](https://en.wikipedia.org/wiki/April_2015_Nepal_earthquake), we lived together for a while and I had to leave him back in Nepal. Below is the pic post-earthquake.\n\n![Mustang and Me](images/me_mustang.jpg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechgaun%2Fex_mustang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftechgaun%2Fex_mustang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechgaun%2Fex_mustang/lists"}