{"id":20677867,"url":"https://github.com/clivern/fred","last_synced_at":"2026-04-15T12:33:20.370Z","repository":{"id":57718270,"uuid":"108048397","full_name":"Clivern/Fred","owner":"Clivern","description":":dragon: A Java Framework for Building Slack Bots.","archived":false,"fork":false,"pushed_at":"2023-12-15T17:29:02.000Z","size":868,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-08T04:29:30.596Z","etag":null,"topics":["chatbot","java","java-library","slack","slack-bot","slackbot"],"latest_commit_sha":null,"homepage":"","language":"Java","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/Clivern.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-23T22:42:26.000Z","updated_at":"2025-01-11T06:38:44.000Z","dependencies_parsed_at":"2022-09-14T22:55:22.188Z","dependency_job_id":null,"html_url":"https://github.com/Clivern/Fred","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/Clivern%2FFred","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FFred/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FFred/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FFred/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Clivern","download_url":"https://codeload.github.com/Clivern/Fred/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242910299,"owners_count":20205265,"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":["chatbot","java","java-library","slack","slack-bot","slackbot"],"created_at":"2024-11-16T21:17:22.386Z","updated_at":"2026-04-15T12:33:20.323Z","avatar_url":"https://github.com/Clivern.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Fred\n====\n\nFred is a Java Framework for Building Slack Bots.\n\n*Current Version: 1.0.2*\n\n[![Build Status](https://travis-ci.org/Clivern/Fred.svg?branch=master)](https://travis-ci.org/Clivern/Fred)\n![](https://img.shields.io/maven-central/v/com.clivern/fred.svg)\n[![Javadocs](http://www.javadoc.io/badge/com.clivern/fred.svg)](http://www.javadoc.io/doc/com.clivern/fred)\n![](https://img.shields.io/github/license/clivern/fred.svg)\n\nInstallation\n------------\nTo add a dependency using Maven, use the following:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.clivern\u003c/groupId\u003e\n  \u003cartifactId\u003efred\u003c/artifactId\u003e\n  \u003cversion\u003e1.0.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nTo add a dependency using Gradle, use the following:\n```java\ndependencies {\n  compile 'com.clivern:fred:1.0.2'\n}\n```\n\nTo add a dependency using Scala SBT, use the following:\n```java\nlibraryDependencies += \"com.clivern\" % \"fred\" % \"1.0.2\"\n```\n\nUsage\n-----\nAfter adding the package as a dependency, Please read the following steps:\n\n### Basic Configurations\n\nIn order to cofigure the package create `config.properties` file with the following data\n\n```java\nclient_id=Application Client ID\nclient_secret=Application Client Secret\nscope=Application Scope\nredirect_uri=Oauth Secured URL\nstate_type=State Type (for example. vary)\nstate=State Key\nteam=Slack Team Name\nverification_token=Verification Token Goes Here\n\nlogging_level=tarce or debug or info or warning or error\nlogging_file_path=src/main/java/resources/\nlogging_file_format=current_date or app\nlogging_log_type=file or console or both\nlogging_current_date_format=yyyy-MM-dd\nlogging_append=true or false\nlogging_buffered=true or false\n```\n\n### Build Oauth Redirect URL\n\nCreate a route to return the Oauth redirect URL like the following:\n\n```java\nimport com.clivern.fred.util.*;\nimport com.mashape.unirest.http.exceptions.UnirestException;\n\n\nConfig config = new Config();\nconfig.loadPropertiesFile(\"config.properties\");\nconfig.configLogger();\nOauth oauth = new Oauth(config, log);\nreturn \"\u003ca href='\" + oauth.getRedirectURL() + \"'\u003eAuth\u003c/a\u003e\";\n```\n\nSo let's say we use [Spark Java Framework](http://sparkjava.com/) for our bot, Our route and callback will look like the following:\n\n```java\nimport static spark.Spark.*;\nimport com.clivern.fred.util.*;\nimport com.mashape.unirest.http.exceptions.UnirestException;\n\npublic class Main {\n\n    public static void main(String[] args) throws UnirestException\n    {\n        get(\"/\", (request, response) -\u003e {\n            Config config = new Config();\n            config.loadPropertiesFile(\"config.properties\");\n            config.configLogger();\n            Oauth oauth = new Oauth(config);\n            return \"\u003ca href='\" + oauth.getRedirectURL() + \"'\u003eAuth\u003c/a\u003e\";\n        });\n    }\n}\n```\n\n### Build Oauth Webhook\n\nIn order to verify the incoming user token and fetch the access token for that user, We will build and a route that do these tasks and we already provided this URL in the `config.properties` file as `redirect_uri`:\n\n```java\nimport static spark.Spark.*;\nimport com.clivern.fred.util.*;\nimport com.mashape.unirest.http.exceptions.UnirestException;\n\n\n\nString code = // Get code query parameter value from the current URL\nString state = // Get state query parameter value from the current URL\nString error = // Get error query parameter value from the current URL\n\nConfig config = new Config();\nconfig.loadPropertiesFile(\"config.properties\");\nconfig.configLogger();\nOauth oauth = new Oauth(config);\n\nBoolean status = oauth.issueToken(code, state, error);\n\nBoolean fetch = oauth.fetchAccessToken();\n\nif( status \u0026\u0026 fetch ){\n\n    return  \"State: \" +  oauth.getState() + \"\u003cbr/\u003e\" +\n            \"Client ID: \" +  oauth.getClientId() + \"\u003cbr/\u003e\" +\n            \"Client Secret: \" +  oauth.getClientSecret() + \"\u003cbr/\u003e\" +\n            \"Scope: \" +  oauth.getScope() + \"\u003cbr/\u003e\" +\n            \"Redirect Uri: \" +  oauth.getRedirectUri() + \"\u003cbr/\u003e\" +\n            \"State Type: \" +  oauth.getStateType() + \"\u003cbr/\u003e\" +\n            \"Team: \" +  oauth.getTeam() + \"\u003cbr/\u003e\" +\n            \"Incoming Code: \" +  oauth.getIncomingCode() + \"\u003cbr/\u003e\" +\n            \"Incoming State: \" +  oauth.getIncomingState() + \"\u003cbr/\u003e\" +\n            \"Incoming Error: \" +  oauth.getIncomingError() + \"\u003cbr/\u003e\" +\n            \"Incoming Access Token: \" +  oauth.getIncomingAccessToken() + \"\u003cbr/\u003e\" +\n            \"Incoming Scope: \" +  oauth.getIncomingScope() + \"\u003cbr/\u003e\" +\n            \"Incoming User ID: \" +  oauth.getIncomingUserId() + \"\u003cbr/\u003e\" +\n            \"Incoming Team Name: \" +  oauth.getIncomingTeamName() + \"\u003cbr/\u003e\" +\n            \"Incoming Team ID: \" +  oauth.getIncomingTeamId() + \"\u003cbr/\u003e\" +\n            \"Incoming Webhook URL: \" +  oauth.getIncomingWebhookUrl() + \"\u003cbr/\u003e\" +\n            \"Incoming Webhook Channel: \" +  oauth.getIncomingWebhookChannel() + \"\u003cbr/\u003e\" +\n            \"Incoming Webhook Config URL: \" +  oauth.getIncomingWebhookConfigUrl() + \"\u003cbr/\u003e\" +\n            \"Incoming Bot User ID: \" +  oauth.getIncomingBotUserId() + \"\u003cbr/\u003e\" +\n            \"Incoming Bot Access Token: \" +  oauth.getIncomingBotAccessToken() + \"\u003cbr/\u003e\";\n\n}else{\n\n    return \"Error\";\n\n}\n```\n\nSo let's say we use [Spark Java Framework](http://sparkjava.com/) for our bot, Our route and callback will look like the following:\n\n```java\nimport static spark.Spark.*;\nimport com.clivern.fred.util.*;\nimport com.mashape.unirest.http.exceptions.UnirestException;\n\n\npublic class Main {\n\n    public static void main(String[] args) throws UnirestException\n    {\n        get(\"/\", (request, response) -\u003e {\n            Config config = new Config();\n            config.loadPropertiesFile(\"config.properties\");\n            config.configLogger();\n            Oauth oauth = new Oauth(config);\n            return \"\u003ca href='\" + oauth.getRedirectURL() + \"'\u003eAuth\u003c/a\u003e\";\n        });\n\n        get(\"/oauth\", (request, response) -\u003e {\n            Config config = new Config();\n            config.loadPropertiesFile(\"config.properties\");\n            config.configLogger();\n            Oauth oauth = new Oauth(config);\n\n            Boolean status = oauth.issueToken(\n                ( request.queryParams(\"code\") != null ) ? request.queryParams(\"code\") : \"\",\n                ( request.queryParams(\"state\") != null ) ? request.queryParams(\"state\") : \"\",\n                ( request.queryParams(\"error\") != null ) ? request.queryParams(\"error\") : \"\"\n            );\n\n            Boolean fetch = oauth.fetchAccessToken();\n\n            if( status \u0026\u0026 fetch ){\n\n                return  \"State: \" +  oauth.getState() + \"\u003cbr/\u003e\" +\n                        \"Client ID: \" +  oauth.getClientId() + \"\u003cbr/\u003e\" +\n                        \"Client Secret: \" +  oauth.getClientSecret() + \"\u003cbr/\u003e\" +\n                        \"Scope: \" +  oauth.getScope() + \"\u003cbr/\u003e\" +\n                        \"Redirect Uri: \" +  oauth.getRedirectUri() + \"\u003cbr/\u003e\" +\n                        \"State Type: \" +  oauth.getStateType() + \"\u003cbr/\u003e\" +\n                        \"Team: \" +  oauth.getTeam() + \"\u003cbr/\u003e\" +\n                        \"Incoming Code: \" +  oauth.getIncomingCode() + \"\u003cbr/\u003e\" +\n                        \"Incoming State: \" +  oauth.getIncomingState() + \"\u003cbr/\u003e\" +\n                        \"Incoming Error: \" +  oauth.getIncomingError() + \"\u003cbr/\u003e\" +\n                        \"Incoming Access Token: \" +  oauth.getIncomingAccessToken() + \"\u003cbr/\u003e\" +\n                        \"Incoming Scope: \" +  oauth.getIncomingScope() + \"\u003cbr/\u003e\" +\n                        \"Incoming User ID: \" +  oauth.getIncomingUserId() + \"\u003cbr/\u003e\" +\n                        \"Incoming Team Name: \" +  oauth.getIncomingTeamName() + \"\u003cbr/\u003e\" +\n                        \"Incoming Team ID: \" +  oauth.getIncomingTeamId() + \"\u003cbr/\u003e\" +\n                        \"Incoming Webhook URL: \" +  oauth.getIncomingWebhookUrl() + \"\u003cbr/\u003e\" +\n                        \"Incoming Webhook Channel: \" +  oauth.getIncomingWebhookChannel() + \"\u003cbr/\u003e\" +\n                        \"Incoming Webhook Config URL: \" +  oauth.getIncomingWebhookConfigUrl() + \"\u003cbr/\u003e\" +\n                        \"Incoming Bot User ID: \" +  oauth.getIncomingBotUserId() + \"\u003cbr/\u003e\" +\n                        \"Incoming Bot Access Token: \" +  oauth.getIncomingBotAccessToken() + \"\u003cbr/\u003e\";\n\n            }else{\n\n                return \"Error\";\n\n            }\n        });\n    }\n}\n```\n\n### Build Slash Commands\n\nSlash Command enable users to interact with your app from within Slack. We will have two tasks to do:\n\n1. First to Create the Commnad on Slack Application and Configure its `Request URL` (The URL that slack will POST the command data once used by any user).\n2. Build a New Route (Accept POST Requests) to handle all Incoming Requests from Slack.\n\nSo Lets Start by the Easy Part `Creating Commands On Slack App`:\n\n1. Please visit [Your Apps Page from Slack.](https://api.slack.com/apps)\n2. Open You App Settings Page (By clicking on the App).\n3. Go to `Slash Commands` From Side Menu Under `Features`.\n4. Then Click to `Create New Command`. A Command Form Will Open To be Filled.\n5. Set the Commnad for example `/fred`.\n6. Set `Request URL` to you Application URL Handling Slack Commands for example `https://b2f78bbb.ngrok.io/commands`.\n7. Set Short Description for example `Launch The Rocket!`.\n8. Set Usage Hint\n9. And Finally Set to `Escape channels, users, and links sent to your app` or Not and Click `Save`.\n\n\nThen Let's Build `Our Route` That will Accept and Process All Incoming Requests from Slack for example `https://b2f78bbb.ngrok.io/commands`. Our route and callback will look like the following Using [Spark Java Framework](http://sparkjava.com/):\n\n```java\nimport static spark.Spark.*;\nimport java.util.HashMap;\nimport java.util.Map;\nimport com.clivern.fred.util.*;\nimport com.clivern.fred.sender.BaseSender;\nimport com.mashape.unirest.http.exceptions.UnirestException;\nimport com.clivern.fred.receiver.BaseReceiver;\nimport com.clivern.fred.receiver.command.Command;\n\n\npublic class Main {\n\n    public static void main(String[] args) throws UnirestException\n    {\n\n        post(\"/commands\", (request, response) -\u003e {\n            Config config = new Config();\n            config.loadPropertiesFile(\"config.properties\");\n            config.configLogger();\n            BaseReceiver baseReceiver = new BaseReceiver(config);\n\n            // Build Our First Command (/fred Command)\n            Command fredCommand = new Command(\"/fred\", false, (ct) -\u003e \"You Typed -\u003e \" + ct.getText() + \" To /fred\");\n\n            // Build Another Command (/frog Command)\n            Command frogCommand = new Command(\"/frog\", false, (ct) -\u003e \"You Typed -\u003e \" + ct.getText() + \" To /frog\");\n\n            // Pass Commands To The Receiver\n            baseReceiver.setCommand(\"/fred\", fredCommand);\n            baseReceiver.setCommand(\"/frog\", frogCommand);\n\n            // Check If Incoming Data Related to Any Configured Command (/fred or /frog)\n            if( baseReceiver.commandExists(request.queryParams(\"command\")) ){\n                Map\u003cString, String\u003e incomingData = new HashMap\u003cString, String\u003e();\n                incomingData.put(\"channel_name\", request.queryParams(\"channel_name\"));\n                incomingData.put(\"user_id\", request.queryParams(\"user_id\"));\n                incomingData.put(\"user_name\", request.queryParams(\"user_name\"));\n                incomingData.put(\"trigger_id\", request.queryParams(\"trigger_id\"));\n                incomingData.put(\"team_domain\", request.queryParams(\"team_domain\"));\n                incomingData.put(\"team_id\", request.queryParams(\"team_id\"));\n                incomingData.put(\"text\", request.queryParams(\"text\"));\n                incomingData.put(\"channel_id\", request.queryParams(\"channel_id\"));\n                incomingData.put(\"command\", request.queryParams(\"command\"));\n                incomingData.put(\"token\", request.queryParams(\"token\"));\n                incomingData.put(\"response_url\", request.queryParams(\"response_url\"));\n\n                return baseReceiver.callCurrentCommand(request.queryParams(\"command\"), incomingData);\n            }\n            return \"Command Not Configured In App!\";\n        });\n    }\n}\n```\n\nNow You Finished, Just go to Slack Messaging and Interact With You Commands. Type `/fred Hello World` and You will Get `You Typed -\u003e Hello World To /fred`.\n\n### Listen To Slack Events\n\nSlack Event API allows your app to be notified of events in Slack (for example, when a user adds a reaction or creates a file) at a URL you choose.\n\nLet's discuss how to implement this using `Fred`.\n\n- [URL Verification Event](docs/events/url_verification.md).\n\n\nMisc\n====\n\nTodo \u0026 Contributing\n-------------------\nIn case you want to share some love, Show your awesomeness in the following sub-packages:\n\n- :rocket: ~~Config and Oauth `com.clivern.fred.util`.~~\n- :rocket: ~~Slash Commands `com.clivern.fred.receiver`.~~\n- :fire: Web API `com.clivern.fred.sender`.\n- :fire: Events API `com.clivern.fred.event`.\n- :rocket: Add More Test Cases.\n- :rocket: Add More Docs.\n- :rocket: Update and Fix Code Docs and Remove Line `32-38` in `maven-push.gradle`.\n- :rocket: Add Examples \u0026 Write Tutorials.\n\nAnd then please do the following:\n\n- Fork the master branch.\n- Create a feature branch `git branch my-feature`.\n- Move to your branch `git checkout my-feature`.\n- Do Your Changes.\n- It will be great if you write some tests to your feature and check `./gradlew test` but not required ;).\n- Track the changes `git add --all`.\n- Commit your changes `git commit -m 'new awesome feature'`.\n- Push to your newly created branch `git push origin my-feature`.\n- Create a new Pull Request.\n\nTutorials \u0026 Examples\n--------------------\n\n\u003e For almost all supported features you can take a look at [`examples/`](https://github.com/Clivern/Fred/tree/master/examples) folder for working examples.\n\nChangelog\n---------\n\nVersion 1.0.2:\n```\nUpdate logging package.\nUpdate Configurations.\n```\n\nVersion 1.0.1:\n```\nAdd Java 8 Support.\n```\n\nVersion 1.0.0:\n```\nInitial Release.\n```\n\nAcknowledgements\n----------------\n\n© 2017, Clivern. Released under [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt).\n\n**Fred** is authored and maintained by [@clivern](http://github.com/clivern).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclivern%2Ffred","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclivern%2Ffred","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclivern%2Ffred/lists"}