-
Notifications
You must be signed in to change notification settings - Fork 27
Sockets - Cyndi and Maria #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
3d87a07
50d8f7a
18580f9
d40ea59
2264e5b
041a674
3f397b0
e11022c
b6f7258
66d4662
8f410b2
91ee437
ecf4c11
697db06
a9ba71f
58b7b46
efc62ed
769c283
3287b9f
30297eb
d385356
e8fd7fd
2823311
264f5af
fa89713
4cabb7c
2f53d3b
a8c729c
2423c69
25304d6
d9442ea
f5a5011
d7b5afb
0a0deca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {"username":"Maria Wissler"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| class SlackApiError < StandardError; end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| require "pry" | ||
| require "httparty" | ||
|
|
||
| class Channel < Recipient | ||
| attr_reader :topic, :member_count | ||
|
|
||
| def initialize(name:, slack_id:, topic:, member_count:) | ||
| super(name: name, slack_id: slack_id) | ||
| @topic = topic | ||
| @member_count = member_count | ||
| end | ||
|
|
||
| def self.list | ||
| response = self.get("channels.list") | ||
| channel_list = [] | ||
| response["channels"].each do |channel| | ||
| name = channel["name"] | ||
| slack_id = channel["id"] | ||
| topic = channel["topic"] | ||
| member_count = channel["members"].count | ||
| channel_list << self.new(name: name, slack_id: slack_id, topic: topic, member_count: member_count) | ||
| end | ||
| return channel_list | ||
| end | ||
|
|
||
| def details | ||
| puts "Name: #{self.name}" | ||
| puts "ID: #{self.slack_id}" | ||
| puts "Topic: #{self.topic["value"]}" | ||
| puts "Number of members: #{self.member_count}" | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| require "pry" | ||
| require "httparty" | ||
|
|
||
| class Recipient | ||
| BASE_URL = "https://slack.com/api/" | ||
|
|
||
| attr_reader :slack_id, :name | ||
|
|
||
| def initialize(slack_id:, name:) | ||
| @slack_id = slack_id | ||
| raise ArgumentError if !name.is_a? String | ||
| @name = name | ||
| end | ||
|
|
||
| def send_message(params) | ||
| endpoint = "chat.postMessage" | ||
| url = BASE_URL + endpoint | ||
| params[:token] = ENV["SLACK_API_TOKEN"] | ||
| response = HTTParty.post(url, body: params) | ||
| unless response.code == 200 && response.parsed_response["ok"] | ||
| raise SlackApiError, response["error"] | ||
| end | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line 21 raises an exception, but not the one you want. Ruby doesn't know what a |
||
| return response | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def self.get(endpoint, params = {}) | ||
| url = BASE_URL + endpoint | ||
| params[:token] = ENV["SLACK_API_TOKEN"] | ||
| response = HTTParty.get(url, query: params) | ||
| unless response.code == 200 && response.parsed_response["ok"] | ||
| raise SlackApiError, response["error"] | ||
| end | ||
| return response | ||
| end | ||
|
|
||
| def self.list | ||
| raise NotImplementedError, "Implement me in a child class!" | ||
| end | ||
|
|
||
| def self.details | ||
| raise NotImplementedError, "Implement me in a child class!" | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,108 @@ | ||
| #!/usr/bin/env ruby | ||
| require "pry" | ||
| require "httparty" | ||
| require "dotenv" | ||
| require_relative "../lib/workspace" | ||
| Dotenv.load | ||
|
|
||
| def display_options | ||
| puts "\nChoose from one of the following:" | ||
| puts "------------------------------" | ||
| puts "\nSelect user" | ||
| puts "\nSelect channel" | ||
| puts "\nDetails" | ||
| puts "\nMessage" | ||
| puts "\nChange Settings" | ||
| puts "\nQuit" | ||
| option = gets.chomp.downcase | ||
| return verify_options(option) | ||
| end | ||
|
|
||
| def verify_options(option) | ||
| options = ["select user", "select channel", "details", "message", "change settings", "quit"] | ||
| until options.include?(option) | ||
| puts "Please input a valid option." | ||
| option = display_options | ||
| end | ||
| return option | ||
| end | ||
|
|
||
| def main | ||
| puts "Welcome to the Ada Slack CLI!" | ||
| puts "\nWhat would you like to do?" | ||
|
|
||
| # TODO project | ||
| option = display_options | ||
| until option == "quit" | ||
| case option | ||
| when "select user" | ||
| puts "You chose to select a user. Please provide a username or Slack ID" | ||
| selected = gets.chomp() | ||
| workspace = Workspace.new(selected: selected) | ||
| recipient = workspace.select_user | ||
| until !recipient.nil? | ||
| puts "Please provide a valid username or Slack ID" | ||
| selected = gets.chomp | ||
| workspace = Workspace.new(selected: selected) | ||
| recipient = workspace.select_user | ||
| end | ||
| puts "You have selected #{recipient.real_name}" | ||
| puts "\nWhat would you like to do next?" | ||
| option = display_options | ||
| when "select channel" | ||
| puts "You chose to select a channel. Please provide a channel name or Slack ID" | ||
| selected = gets.chomp() | ||
| workspace = Workspace.new(selected: selected) | ||
| recipient = workspace.select_channel | ||
| until !recipient.nil? | ||
| puts "Please provide a valid Channel name or Slack ID" | ||
| selected = gets.chomp | ||
| workspace = Workspace.new(selected: selected) | ||
| recipient = workspace.select_channel | ||
| end | ||
| puts "You have selected #{recipient.name}" | ||
| option = display_options | ||
| when "details" | ||
| begin | ||
| workspace.show_details(recipient) | ||
| puts "\nWhat would you like to do next?" | ||
| option = display_options | ||
| rescue | ||
| puts "You must select a user or channel first." | ||
| puts "\nWhat would you like to do next?" | ||
| option = display_options | ||
| end | ||
| when "message" | ||
| begin | ||
| recipient.slack_id #checking if recipient exists; if it doesn't will throw name error => rescue clause | ||
| puts "What message would you like to send?" | ||
| message = gets.chomp | ||
| workspace.send_message(message, recipient) | ||
| puts "\nYou're message has been sent." | ||
| puts "\nWhat would you like to do next?" | ||
| option = display_options | ||
| rescue | ||
| puts "You must select a user or channel first." | ||
| puts "\nWhat would you like to do next?" | ||
| option = display_options | ||
| end | ||
| when "change settings" | ||
| puts "You can change the username displayed" | ||
| # puts "Please type either 'username' or 'icon emoji' or both to change either" | ||
| puts "What username would you like to use?" | ||
| setting_username_change = gets.chomp | ||
| params = {} | ||
| params[:username] = setting_username_change | ||
| Workspace.save_settings(params) | ||
| puts "Thanks, username is now #{setting_username_change}." | ||
| puts "Quit and restart the program for this change to be implemented" | ||
| option = display_options | ||
| end | ||
| end | ||
|
|
||
| puts "Thank you for using the Ada Slack CLI" | ||
| end | ||
|
|
||
| main if __FILE__ == $PROGRAM_NAME | ||
| main if __FILE__ == $PROGRAM_NAME | ||
|
|
||
| def verify_icon_emojis | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| require "pry" | ||
| require "httparty" | ||
| require_relative "recipient.rb" | ||
|
|
||
| class User < Recipient | ||
| attr_reader :real_name, :status_text, :status_emoji | ||
|
|
||
| def initialize(name:, slack_id:, real_name:, status_text: nil, status_emoji: nil) | ||
| super(name: name, slack_id: slack_id) | ||
| @real_name = real_name | ||
| @status_text = status_text | ||
| @status_emoji = status_emoji | ||
| end | ||
|
|
||
| def self.list #factory method | ||
| response = self.get("users.list") | ||
| user_list = [] | ||
| response["members"].each do |member| | ||
| name = member["name"] | ||
| slack_id = member["id"] | ||
| real_name = member["real_name"] | ||
| status_text = member["profile"]["status_text"] | ||
| status_emoji = member["profile"]["status_emoji"] | ||
| user_list << self.new(name: name, slack_id: slack_id, real_name: real_name, status_text: status_text, status_emoji: status_emoji) | ||
| end | ||
| return user_list | ||
| end | ||
|
|
||
| def details #business logic | ||
| puts "Username: #{self.name}" | ||
| puts "ID: #{self.slack_id}" | ||
| puts "Name: #{self.real_name}" | ||
| puts "Status: #{self.status_text}" | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| require "httparty" | ||
| require_relative "../lib/user" | ||
| require_relative "../lib/channel" | ||
| require_relative "../lib/recipient" | ||
| require "json" | ||
|
|
||
| class Workspace | ||
| attr_reader :users, :channels, :selected | ||
|
|
||
| def initialize(selected:) | ||
| @users = User.list | ||
| @channels = Channel.list | ||
| @selected = selected # either user or channel info | ||
| end | ||
|
|
||
| def select_user | ||
| user_selected = users.detect do |user| | ||
| user.slack_id == selected || user.name == selected | ||
| end | ||
| return user_selected | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good use of the Since this doesn't save the user in |
||
| end | ||
|
|
||
| def select_channel | ||
| channel_selected = channels.detect do |channel| | ||
| channel.slack_id == selected || channel.name == selected | ||
| end | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is very similar to the code for |
||
| return channel_selected | ||
| end | ||
|
|
||
| def self.save_settings(params) | ||
| settings_file = File.open("bot-settings.json", "w") do |f| | ||
| f.write(params.to_json) | ||
| end | ||
| end | ||
|
|
||
| def bot_settings_file_exist | ||
| begin | ||
| readfile = File.read("bot-settings.json") | ||
| return readfile | ||
| rescue | ||
| readfile = nil | ||
| end | ||
| end | ||
|
|
||
| def send_message(message, recipient) | ||
| params = {} | ||
| params[:text] = message | ||
| params[:channel] = recipient.slack_id | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of taking the recipient as an argument here, you should send the message to whatever is saved in |
||
| readfile = bot_settings_file_exist #check if settings have been changed | ||
| params.merge!(eval(readfile)) if !readfile.nil? | ||
| recipient.send_message(params) | ||
| end | ||
|
|
||
| def show_details(recipient) | ||
| recipient.details | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| "{:username=>""cyndi""}" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| require_relative "test_helper" | ||
| require "pry" | ||
| describe "channel class" do | ||
| describe "initialize" do | ||
| it "creates and instance of channel" do | ||
| topic = "random" | ||
| member_count = 3 | ||
| name = "cyndilopez6" | ||
| slack_id = 1 | ||
| expect(Channel.new(name: name, slack_id: slack_id, topic: topic, member_count: member_count)).must_be_kind_of Channel | ||
| end | ||
| end | ||
|
|
||
| describe "can connect to API" do | ||
| it "accesses api" do | ||
| VCR.use_cassette("connect to endpoints channels_list") do | ||
| endpoint = "channels.list" | ||
| @response = Channel.get(endpoint) | ||
| end | ||
| expect(@response.code == 200 && @response.parsed_response["ok"]).must_equal true | ||
| end | ||
| end | ||
|
|
||
| describe "raises errors for incorrect endpoint" do | ||
| it "raises an error for incorrect endpoint" do | ||
| VCR.use_cassette("check_method_error_raised") do | ||
| endpoint = "ret424252E#1231+=.y" | ||
| exception = expect { Channel.get(endpoint) }.must_raise SlackApiError | ||
| expect(exception.message).must_equal "unknown_method" | ||
| end | ||
| end | ||
|
|
||
| # it "raises an error for incorrect token" do | ||
| # VCR.use_cassette("check_auth_error_raised") do | ||
| # endpoint = "channels.list" | ||
| # params = {:token => "0123456789abcdef"} | ||
| # p params | ||
| # expect(Channel.get(endpoint, params)).must_equal "invalid_auth" | ||
| # end | ||
| # end | ||
| end | ||
|
|
||
| describe "creates list of channels" do | ||
| it "returns a type of array" do | ||
| VCR.use_cassette("returns array") do | ||
| expect(Channel.list.is_a? Array).must_equal true | ||
| end | ||
| end | ||
|
|
||
| it "returns an array of Channel objects" do | ||
| VCR.use_cassette("returns object Channel") do | ||
| expect(Channel.list[0]).must_be_kind_of Channel | ||
| end | ||
| end | ||
|
|
||
| it "returns an accurate list of channels in slack workspace" do | ||
| VCR.use_cassette("correct channels") do | ||
| expect(Channel.list.map { |channel| channel.name }.length).must_be :>, 0 | ||
| end | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| require_relative "test_helper" | ||
| require "pry" | ||
| describe "recipient class" do | ||
| describe "initialize" do | ||
| it "creates an instance of Recipient" do | ||
| #check slack_if format | ||
| slack_id = 1 | ||
| name = "Maria" | ||
| expect(Recipient.new(slack_id: slack_id, name: name)).must_be_kind_of Recipient | ||
| end | ||
|
|
||
| it "raises an argument error if name is not a string" do | ||
| expect { Recipient.new(slack_id: 1, name: 21) }.must_raise ArgumentError | ||
| end | ||
| end | ||
|
|
||
| describe "can connect to API" do | ||
| it "can connect" do | ||
| VCR.use_cassette("find channels") do | ||
| response = Recipient.get("channels.list") | ||
| expect(response["channels"]).wont_be_nil | ||
| expect(response["channels"].map { |channel| channel["name"] }.length).must_be :>, 0 | ||
| end | ||
| end | ||
|
|
||
| it "gives a list with more than one user name" do | ||
| VCR.use_cassette("find channels") do | ||
| endpoint = "users.list" | ||
| response = Recipient.get(endpoint) | ||
| # Binding.pry | ||
| expect(response).wont_be_nil | ||
| expect(response["members"].map { |member| member["name"] }.length).must_be :>, 0 | ||
| end | ||
| end | ||
| it "can find the status of a member" do | ||
| VCR.use_cassette("user status") do | ||
| endpoint = "users.list" | ||
| response = Recipient.get(endpoint) | ||
| expect(response["members"][0]["profile"]["status_text"].length).wont_be_nil | ||
| expect(response["members"].select { |member| member["real_name"] == "Maria Wissler" }[0]["profile"]["status_text"]).must_be_kind_of String | ||
| end | ||
| end | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best practice is to avoid explicit type checking in a dynamic language like Ruby. This is for two reasons. First, if
namereally needs to be a String, then we'll get an error soon enough one way or the other. Second, if the user passes in something that close enough to a string to work (i.e. implements the String interface), there's no reason for our code to fail.