diff --git a/README.md b/README.md index ade65f8..e044d75 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,15 @@ # Access Code 3.3 - Slack Bot Challenge 🤖
-A [Slack bot](https://api.slack.com/bot-users) is a non-human "user" that interacts with the Slack messaging app. Bots might post messages to users or to channels, send reminders, look up information in response to a question or perform a calculation. In this project, we'll work in teams to build bots that can preform simple interactions with the AccessCode3-3 Slack. +A [Slack bot](https://api.slack.com/bot-users) is a non-human "user" that interacts with the Slack messaging app. +Bots might post messages to users or to channels, send reminders, look up information in response to a question or perform a calculation. In this project, we'll work in teams to build bots that can preform simple interactions with the AccessCode3-3 Slack. ![slack bot example](https://api.slack.com/img/api/guide_bot_user.png) -Slack offers three different APIs that developers can use to interact with their service: the Web API, the Real Time Messaging API and the Events API . In this project, bots will only interact using the [Web API](https://api.slack.com/web). The Web API offers methods that can be used to list AccessCode3-3 channels, view message history on a given channel, and post and delete messages on the #bots channel. +Slack offers three different APIs that developers can use to interact with their service: the Web API, the Real Time Messaging +API and the Events API . In this project, bots will only interact using the [Web API](https://api.slack.com/web). +The Web API offers methods that can be used to list AccessCode3-3 channels, view message history on a given channel, and +post and delete messages on the #bots channel. +
## Setup The following setup steps only need to be completed **once per team**: @@ -13,12 +18,14 @@ The following setup steps only need to be completed **once per team**: 2. Go to https://accesscode3-3.slack.com/apps/new/A0F7YS25R-bots. Make sure you are signed into the AccessCode3-3 Slack team. Choose a username for your bot and click the "Add bot integration" button. -3. Make a note of your **API token**. The token must always be kept in a **safe, secret** place. We will be storing our API keys in the `../SlackBot/api_token.txt` file, which has been added to our `.gitignore` file. +3. Make a note of your **API token**. The token must always be kept in a **safe, secret** place. We will be storing our API keys in the +`../SlackBot/api_token.txt` file, which has been added to our `.gitignore` file. > Always be careful when sharing API tokens! Be careful to never publish > our bot user tokens in any public GitHub code repository. -4. Complete your bot's profile. Add an avatar image/emoji, a first and last name and a description of what your bot does. When you are finished, click the "Save Integration" button. +4. Complete your bot's profile. Add an avatar image/emoji, a first and last name and a description of what your bot does. +When you are finished, click the "Save Integration" button. 5. **Both team members:** join the #bots channel on Slack so you can see what your bot is up to. @@ -26,16 +33,20 @@ The following setup steps only need to be completed **once per team**: 1. Form a clear picture of the project requirements. Spend some time reading through: - This readme doc. - The [Slack Web API docs](https://api.slack.com/web) and [Basic message formatting guidelines](https://api.slack.com/docs/message-formatting). - - The code that has been provided in the `SlackBot` project -- particulary the Slack.java class, which provides methods that your bot can use to interact with Slack's Web API. + - The code that has been provided in the `SlackBot` project -- particulary the Slack.java class, which provides + methods that your bot can use to interact with Slack's Web API. - Use the IntelliJ TODO panel (⌘6) to navigate to each of the project TODOs. -2. For both of the following Slack API JSON objects, write a Java class to parse and represent it as a Java object. Each team member should be responsible for parsing at least one of the classes: +2. For both of the following Slack API JSON objects, write a Java class to parse and represent it as a Java object. +Each team member should be responsible for parsing at least one of the classes: - [user](https://api.slack.com/types/user) -> User.java - [attachment](https://api.slack.com/docs/message-attachments) -> Attachment.java - Attachment.java and User.java files are already provided in the `model` subpackage -- just complete the TODOs as marked. See the Channel.java class for an example of how your completed classes should look. + Attachment.java and User.java files are already provided in the `model` subpackage -- just complete the TODOs as marked. + See the Channel.java class for an example of how your completed classes should look. -3. In Bot.java, design and implement your bot code! It's up to your team to decide what your bot does, but at a minimum, when your program runs it should post a message with some content to the #bots channel. See below for some ideas. +3. In Bot.java, design and implement your bot code! It's up to your team to decide what your bot does, but at a minimum, +when your program runs it should post a message with some content to the #bots channel. See below for some ideas. 4. (Optional / Bonus!) In `Slack.java`, implement the `sendMessageWithAttachments(String messageText, List attachments)`, which should take in a `String messageText` and a `List attachments` to post to the #bots channel. It should return a `SendMessageResponse`. If your bot will send messages with attachments, you must implement this method. Read https://api.slack.com/docs/message-attachments to familiarize yourself with how attachment URL parameters should be formatted. diff --git a/src/nyc/c4q/ramonaharrison/Bot.java b/src/nyc/c4q/ramonaharrison/Bot.java index 6a52dd4..476d117 100644 --- a/src/nyc/c4q/ramonaharrison/Bot.java +++ b/src/nyc/c4q/ramonaharrison/Bot.java @@ -1,11 +1,12 @@ package nyc.c4q.ramonaharrison; - +import java.util.*; +import java.net.*; import nyc.c4q.ramonaharrison.model.Channel; import nyc.c4q.ramonaharrison.model.Message; import nyc.c4q.ramonaharrison.network.*; import nyc.c4q.ramonaharrison.network.response.*; -import java.util.List; +import java.util.*; /** * Created by Ramona Harrison @@ -15,14 +16,60 @@ public class Bot { // TODO: implement your bot logic! + private static HashMap keyWords; public Bot() { + sendMessageToBotsChannel("Fancy"); + //listMessages("bots"); + } + + /** * Sample method: tests the Slack API. Prints a message indicating success or failure. */ + + + public class Keywords { + + public Keywords(){ + addWord("sad"); + addWord("happy"); + addWord("anxious"); + addWord("content"); + addWord("hurt"); + addWord("insulted"); + addWord("lyrical"); + } + + private HashMap>words = new HashMap<>(); + + private char getFirstLetter(String string){ + char[] word = string.toCharArray(); + return word[1]; + } + + private void addWord(String string){ + if(words.containsKey(getFirstLetter(string))) { + words.get(getFirstLetter(string)).add(string); + } else { + ArrayList thisLetter = new ArrayList(); + thisLetter.add(string); + words.put(getFirstLetter(string),thisLetter); + } + } + + private boolean searchFor(String string){ + return words.get(getFirstLetter(string)).contains(string); + } + } + + + + + public void testApi() { Response apiTest = Slack.testApi(); System.out.println("API OK: " +apiTest.isOk() + "\n"); diff --git a/src/nyc/c4q/ramonaharrison/model/Attachment.java b/src/nyc/c4q/ramonaharrison/model/Attachment.java index 8b9d1ef..2106dee 100644 --- a/src/nyc/c4q/ramonaharrison/model/Attachment.java +++ b/src/nyc/c4q/ramonaharrison/model/Attachment.java @@ -11,29 +11,139 @@ * */ -public class Attachment { - // TODO: implement private fields for each of the following attachment JSON keys: - // "fallback" - // "color" - // "pretext" - // "author_name" - // "author_link" - // "author_icon" - // "title" - // "title_link" - // "text" - // "fields" - // "image_url" - // "thumb_url" - // "footer" - // "footer_icon" - // "ts" + +public class Attachment { + private String fallback; + private String color; + private String pretext; + private String author_name; + private String author_link; + private String author_icon; + private String title; + private String title_link; + private String text; + private String fields; + private String image_url; + private String thumb_url; + private String footer; + private String footer_icon; + private String ts; public Attachment(JSONObject json) { // TODO: parse an attachment from the incoming json + if (json.get("fallback") != null) { + this.fallback = (String) json.get("fallback"); + } + + if (json.get("color") != null) { + this.color = (String) json.get("color"); + } + + if (json.get("pretext") != null) { + this.pretext = (String) json.get("pretext"); + } + + if (json.get("author_name") != null) { + this.author_name = (String) json.get("author_name"); + } + + if (json.get("author_link") != null) { + this.author_link = (String) json.get("author_link"); + } + + if (json.get("author_icon") != null) { + this.author_icon = (String) json.get("author_icon"); + } + if (json.get("title") != null) { + this.title = (String) json.get("title"); + } + if (json.get("title_link") != null) { + this.title_link = (String) json.get("title_link"); + } + if (json.get("text") != null) { + this.text = (String) json.get("text"); + } + if (json.get("fields") != null) { + this.fields = (String) json.get("fields"); + } + if (json.get("image_url") != null) { + this.image_url = (String) json.get("image_url"); + } + if (json.get("thumb_url") != null) { + this.thumb_url = (String) json.get("thumb_url"); + } + if (json.get("footer") != null) { + this.footer = (String) json.get("footer"); + } + if (json.get("footer_icon") != null) { + this.footer_icon = (String) json.get("footer_icon"); + } + if (json.get("ts") != null) { + this.ts = (String) json.get("ts"); + } } // TODO add getters to access private fields + public String getFallback() { + return fallback; + } + + public String getColor() { + return color; + } + + public String getPretext() { + return pretext; + } + + public String getAuthor_name() { + return author_name; + } + + public String getAuthor_link() { + return author_link; + } + + public String getAuthor_icon() { + return author_icon; + } + + public String getTitle() { + return title; + } + + public String getTitle_link() { + return title_link; + } + + public String getText() { + return text; + } + + public String getFields() { + return fields; + } + + public String getImage_url() { + return image_url; + } + + public String getThumb_url() { + return thumb_url; + } + + public String getFooter() { + return footer; + } + + public String getFooter_icon() { + return footer_icon; + } + + public String getTs() { + return ts; + } + } diff --git a/src/nyc/c4q/ramonaharrison/model/Keywords.java b/src/nyc/c4q/ramonaharrison/model/Keywords.java new file mode 100644 index 0000000..deebefd --- /dev/null +++ b/src/nyc/c4q/ramonaharrison/model/Keywords.java @@ -0,0 +1,40 @@ +package nyc.c4q.ramonaharrison.model; +import java.util.*; +import java.net.*; + +public class Keywords { + + public Keywords(){ + addWord("sad"); + addWord("happy"); + addWord("anxious"); + addWord("content"); + addWord("hurt"); + addWord("insulted"); + addWord("lyrical"); + } + + private HashMap>words = new HashMap<>(); + + private char getFirstLetter(String string){ + char[] word = string.toCharArray(); + return word[1]; + } + + private void addWord(String string){ + if(words.containsKey(getFirstLetter(string))) { + words.get(getFirstLetter(string)).add(string); + } else { + ArrayList thisLetter = new ArrayList(); + thisLetter.add(string); + words.put(getFirstLetter(string),thisLetter); + } + } + + private boolean searchFor(String string){ + return words.get(getFirstLetter(string)).contains(string); + } +} + + + diff --git a/src/nyc/c4q/ramonaharrison/model/Message.java b/src/nyc/c4q/ramonaharrison/model/Message.java index 8ea24bd..b0ca52a 100644 --- a/src/nyc/c4q/ramonaharrison/model/Message.java +++ b/src/nyc/c4q/ramonaharrison/model/Message.java @@ -53,9 +53,10 @@ public Message(JSONObject json) { this.attachments = new ArrayList(); for (int i = 0; i < attachmentsArray.size(); i++) { this.attachments.add(new Attachment((JSONObject) attachmentsArray.get(i))); + } - } + } } public String getText() { diff --git a/src/nyc/c4q/ramonaharrison/model/User.java b/src/nyc/c4q/ramonaharrison/model/User.java index bc309eb..135be30 100644 --- a/src/nyc/c4q/ramonaharrison/model/User.java +++ b/src/nyc/c4q/ramonaharrison/model/User.java @@ -1,6 +1,9 @@ package nyc.c4q.ramonaharrison.model; import org.json.simple.JSONObject; +import org.json.simple.JSONArray; +import java.util.ArrayList; +import java.util.List; /** * Created by Ramona Harrison @@ -15,22 +18,142 @@ public class User { // TODO: implement private fields for each of the following user JSON keys: // "id" + private String id; // "name" + private String name; // "deleted" + private boolean deleted; // "color" + private String color; // "profile" + private List profile; // "is_admin" + private boolean is_admin; // "is_owner" + private boolean is_owner; // "is_primary_owner" + private boolean is_primary_owner; // "is_restricted" + private boolean is_restricted; // "is_ultra_restricted" + private boolean is_ultra_restricted; // "has_2fa" + private boolean has_2fa; // "two_factor_type" + private String two_factor_type; // "has_files" + private boolean has_files; public User(JSONObject json) { // TODO: parse a user from the incoming json + if (json.get("id") != null) { + this.id = (String) json.get("id"); + } + + if (json.get("name") != null) { + this.name = (String) json.get("name"); + } + + if (json.get("deleted") != null) { + this.deleted = (boolean) json.get("deleted"); + } + + if(json.get("color") != null) { + this.color = (String) json.get("color"); + } + + if (json.get("profile") != null) { + JSONArray profileArray = (JSONArray) json.get("profile"); + this.profile = new ArrayList(); + for (int i = 0; i < profileArray.size(); i++) { + this.profile.add((String) profileArray.get(i)); + } + } + + if (json.get("is_admin") != null) { + this.is_admin = (boolean) json.get("is_admin"); + } + + if (json.get("is_owner") != null) { + this.is_owner = (boolean) json.get("is_owner"); + } + + if (json.get("is_primary_owner") != null) { + this.is_primary_owner = (boolean) json.get("is_primary_owner"); + } + + if (json.get("is_restricted") != null) { + this.is_restricted = (boolean) json.get("is_restricted"); + } + + if (json.get("is_ultra_restricted") != null) { + this.is_ultra_restricted = (boolean) json.get("is_ultra_restricted"); + } + + if (json.get("has_2fa") != null) { + this.has_2fa = (boolean) json.get("has_2fa"); + } + + if (json.get("two_factor_type") != null) { + this.two_factor_type = (String) json.get("two_factor_type"); + } + + if (json.get("has_files") != null) { + this.has_files = (boolean) json.get("has_files"); + } } // TODO add getters to access private fields + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public boolean isDeleted() { + return deleted; + } + + public String getColor() { + return color; + } + + public List getProfile() { + return profile; + } + + public boolean isIs_admin() { + return is_admin; + } + + public boolean isIs_owner() { + return is_owner; + } + + public boolean isIs_primary_owner() { + return is_primary_owner; + } + + public boolean isIs_restricted() { + return is_restricted; + } + + public boolean isIs_ultra_restricted() { + return is_ultra_restricted; + } + + public boolean isHas_2fa() { + return has_2fa; + } + + public String getTwo_factor_type() { + return two_factor_type; + } + + public boolean isHas_files() { + return has_files; + } }