Skip to content
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

Sockets - Sarah/Riyo #14

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ba612ba
created file structure
sjscotton Mar 19, 2019
155a5c2
added tests to spec files
RPerry Mar 19, 2019
401fb02
Added recipient.list
sjscotton Mar 19, 2019
0f46e26
Added user self.list
sjscotton Mar 19, 2019
309e1b3
Added self.list to channel class
RPerry Mar 19, 2019
3b207ce
added workspace class and spec
RPerry Mar 19, 2019
c6fed72
Added main loop in main.rb
sjscotton Mar 19, 2019
3f71bb8
added table_print for list user and channels
RPerry Mar 20, 2019
f614e2a
moved base_url to recipient
RPerry Mar 20, 2019
4e9634d
added user initialize
sjscotton Mar 20, 2019
83002b0
added user details method
RPerry Mar 20, 2019
017bbc0
Added workspace list users
sjscotton Mar 20, 2019
867f4bd
added initialize and details to channel
RPerry Mar 21, 2019
ac71720
added tests for list_users and list_channels for workspace
RPerry Mar 21, 2019
45da5c8
Updated slack.rb to include select users, channels and details in the…
sjscotton Mar 21, 2019
b210b3c
Added send message to recipient
sjscotton Mar 22, 2019
95d61b8
added send message to workspace
sjscotton Mar 22, 2019
b2e70ab
send message tests for workspace, user and channel
RPerry Mar 22, 2019
0641e19
added send message to main
sjscotton Mar 22, 2019
4a3cd03
edited error message
sjscotton Mar 22, 2019
c9a69fa
Merge branch 'master' of https://github.com/sjscotton/slack-cli
sjscotton Mar 22, 2019
d080994
Added user input validation to slack.rb
sjscotton Mar 22, 2019
e1e40f9
added self.get method
RPerry Mar 22, 2019
50f4ddf
cleaned up tests
RPerry Mar 22, 2019
0ed53f2
refactored check response code into a method
sjscotton Mar 22, 2019
29c7e1d
changed .must_equal nil to assert_nil
sjscotton Mar 29, 2019
bf083fa
fixed no 0 parameter error in main
sjscotton Apr 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions lib/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module SlackBot
class Channel < Recipient
PATH_URL = "channels.list?"
attr_reader :num_members, :name, :id

def initialize(num_members:, name:, id:)
@num_members = num_members
@name = name
@id = id
end

def self.list
response = get(PATH_URL)
check_response_code(response)

channels_array = response["channels"].map do |channel|
SlackBot::Channel.new(num_members: channel["num_members"], name: channel["name"], id: channel["id"])
end

return channels_array
end

def details
channel_details = {
num_members: @num_members,
name: @name,
id: @id,
}
return channel_details
end
end
end
43 changes: 43 additions & 0 deletions lib/recipient.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module SlackBot
class SlackApiError < StandardError; end

class Recipient
BASE_URL = "https://slack.com/api/"
TOKEN = ENV["TOKEN"]
def self.list
raise NotImplementedError
end

def details
raise NotImplementedError
end

def send_message(message)
body = {
text: message,
channel: id,
token: TOKEN,
}
response = HTTParty.post("#{BASE_URL}chat.postMessage", body: body, headers: { "Content-type" => "application/x-www-form-urlencoded" })
unless response.code == 200 && response.parsed_response["ok"]
raise SlackApiError, "Error when posting #{message} to #{id}, error: #{response.parsed_response["error"]}"
end

return true
end

def self.check_response_code(response)
unless response.code == 200 && response.parsed_response["ok"]
raise SlackApiError, "Error when posting #{message} to #{id}, error: #{response.parsed_response["error"]}"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This references message and id but those methods aren't defined here and the variables aren't passed in.

I suspect message should be a parameter here and id should be an attr_reader and required by initialize (since you want all Recipients to have an id).

end
end

private

def self.get(path_url)
query_parameters = { token: TOKEN }
response = HTTParty.get("#{BASE_URL}#{path_url}", query: query_parameters)
return response

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have liked to see check_response_code called inside of self.get instead of outside. If you have to validate separately then it's easy to forget.

end
end
end
84 changes: 82 additions & 2 deletions lib/slack.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,91 @@
#!/usr/bin/env ruby
require "table_print"
require "HTTParty"
require "dotenv"
Dotenv.load

require_relative "../lib/recipient.rb"
require_relative "../lib/user.rb"
require_relative "../lib/channel.rb"
require_relative "../lib/workspace.rb"

def get_user_options_input(options)
input = gets.chomp.to_s.strip

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor issue: .to_s is redundant here (gets already gives you a string).

until options.include?(input)
puts "Please choose option from list"
input = gets.chomp.to_s.strip
end
puts "\n"
return input
end

def get_user_input(message_to_user)
input = gets.chomp.to_s.strip
until input.length > 0
puts message_to_user
input = gets.chomp.to_s.strip
end
puts "\n"
return input
end

def list_options
puts "\nPlease choose from these options:\n\n"
puts "Enter 'list users' to view all users"
puts "Enter 'list channels' to view all channels"
puts "Enter 'select user' to select a user"
puts "Enter 'select channel' to select a channel"
puts "Enter 'details' to display information about currently selected recipient"
puts "Enter 'send message' to send a message to selected recipient"
puts "Enter 'quit' to quit\n\n"
end

def main
puts "Welcome to the Ada Slack CLI!"
workspace = SlackBot::Workspace.new

# TODO project
while true
list_options
options = ["list users", "list channels", "select user", "select channel", "details", "send message", "quit"]
choice = get_user_options_input(options)
case choice
when "list users"
tp workspace.list_users
when "list channels"
tp workspace.list_channels
when "select user"
puts "Please enter a user ID or user name:"
input = get_user_input("Please enter an ID or name")
selected = workspace.select_user(input)
puts "Sorry, no user with that information" if selected == nil
when "select channel"
puts "Please enter a channel name channel ID"
input = get_user_input("Please enter an ID or name")
selected = workspace.select_channel(input)
puts "Sorry, no channel with that information" if selected == nil
when "details"
if workspace.selected
tp [selected.details]
else
puts "Please select a user or channel first"
end
when "send message"
if !workspace.selected
puts "A recipient needs to be selected first"
else
puts "Enter the message you would like to send: "
message_to_send = get_user_input("Message must be at least one character")
workspace.send_message(message_to_send)
puts "Message sent!"
end
when "quit"
puts "Goodbye!"
exit
end
puts "\n\n"
end

puts "Thank you for using the Ada Slack CLI"
end

main if __FILE__ == $PROGRAM_NAME
main if __FILE__ == $PROGRAM_NAME
Empty file added lib/slack_api_error.rb
Empty file.
34 changes: 34 additions & 0 deletions lib/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require "pry"

module SlackBot
class User < Recipient
PATH_URL = "users.list?"
attr_reader :real_name, :name, :id

def initialize(real_name:, name:, id:)
@real_name = real_name
@name = name
@id = id
end

def self.list
response = get(PATH_URL)
check_response_code(response)

users_array = response["members"].map do |user|
SlackBot::User.new(real_name: user["real_name"], name: user["name"], id: user["id"])
end

return users_array
end

def details
user_details = {
real_name: @real_name,
name: @name,
id: @id,
}
return user_details
end
end
end
45 changes: 45 additions & 0 deletions lib/workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module SlackBot
class Workspace
attr_reader :users, :channels, :selected

def initialize
@users = SlackBot::User.list
@channels = SlackBot::Channel.list
@selected = nil
end

def list_users
user_list = @users.map do |user|
user.details
end
return user_list
end

def list_channels
channel_list = @channels.map do |channel|
channel.details
end
return channel_list
end

def select_user(input)
found_user = @users.find do |user|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of find.

input == user.id || input == user.name
end
@selected = found_user

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you aren't going to do additional validation you can just directly assign @selected to found_user.

end

def select_channel(input)
found_channel = @channels.find do |channel|
input == channel.id || input == channel.name
end
@selected = found_channel
end

def send_message(message)
return false if !selected

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you checked for selected here.

Remember, you can use unless selected instead of if !selected to clarify things a touch (though that's mostly a matter of personal preference).

Suggested change
return false if !selected
return false unless selected

selected.send_message(message)
return true
end
end
end
47 changes: 47 additions & 0 deletions specs/channel_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require_relative "test_helper"

describe "channel" do
describe "self.list" do
it "Returns an array of hashes" do
VCR.use_cassette("self.list") do
channel_list = SlackBot::Channel.list

expect(channel_list).must_be_kind_of Array
expect(channel_list.first).must_be_kind_of SlackBot::Channel
expect(channel_list.last).must_be_kind_of SlackBot::Channel
end
end
it "Returns a real_name" do
VCR.use_cassette("self.list") do
channel_list = SlackBot::Channel.list

expect(channel_list.first.num_members).must_equal 2
expect(channel_list.first.id).must_equal "CH2P99HT5"
expect(channel_list.first.name).must_equal "slack-api-project"
end
end
end
describe "send message" do
before do
VCR.use_cassette("send message to channel") do
@channel_list = SlackBot::Channel.list
end
end

it "returns true if given a valid message" do
VCR.use_cassette("send message with empty string to channel") do
message = "Hello!"
expect(@channel_list.first.send_message(message)).must_equal true
end
end

it "returns a slackapierror when given an empty string" do
VCR.use_cassette("send message with empty string to channel") do
message = ""
expect {
@channel_list.first.send_message(message)
}.must_raise SlackBot::SlackApiError
end
end
end
end
20 changes: 20 additions & 0 deletions specs/recipient_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require_relative "test_helper"

describe "Recipient" do
describe "self.list" do
it "Raises NotImplementedError if called directly on recipient" do
expect {
SlackBot::Recipient.list
}.must_raise NotImplementedError
end
end

describe "details" do
it "Raise NotImplementedError if called directory on recipient" do
recipient = SlackBot::Recipient.new
expect {
recipient.details
}.must_raise NotImplementedError
end
end
end
32 changes: 25 additions & 7 deletions specs/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
require 'simplecov'
require "simplecov"
SimpleCov.start

require 'minitest'
require 'minitest/autorun'
require 'minitest/reporters'
require 'minitest/skip_dsl'
require 'vcr'
require "minitest"
require "minitest/autorun"
require "minitest/reporters"
require "minitest/skip_dsl"
require "HTTParty"
require "vcr"
require "webmock/minitest"
require "dotenv"
require "pry"
Dotenv.load

Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new

VCR.configure do |config|
config.cassette_library_dir = "specs/cassettes"
config.hook_into :webmock
end
config.default_cassette_options = {
:record => :new_episodes,
:match_requests_on => [:method, :uri, :body],
}

config.filter_sensitive_data("<SLACK_TOKEN>") do
ENV["TOKEN"]
end
end

require_relative "../lib/recipient.rb"
require_relative "../lib/user.rb"
require_relative "../lib/channel.rb"
require_relative "../lib/workspace.rb"
Loading