Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1bf4bfb
Added recipient test.
minipaige02 Sep 10, 2019
c7d314f
updated Recipient and its test
geli-gel Sep 10, 2019
2be7169
added file for User and test
geli-gel Sep 10, 2019
3aedac1
Added remaining classes and initialize tests.
minipaige02 Sep 10, 2019
cc78eca
created self.list in User and test
geli-gel Sep 10, 2019
fede551
added self.get to Recipient and refactored User self.list to use pare…
geli-gel Sep 10, 2019
0875424
Delete list_users.yml
geli-gel Sep 10, 2019
c89c942
Hid the API token and other small edits.
minipaige02 Sep 10, 2019
09d3f01
Added self.list method and tests.
minipaige02 Sep 10, 2019
a16cf80
update list_users.yml
minipaige02 Sep 10, 2019
d727d4b
updated Workspace to initialize with User and Channel .list and added…
geli-gel Sep 11, 2019
19d7b70
Added test for workspace initialize.
minipaige02 Sep 11, 2019
62270c4
small changes to require and require_relative
geli-gel Sep 11, 2019
ef7d608
retested VCR
geli-gel Sep 11, 2019
84b14fd
created CLI and menu_options method
geli-gel Sep 11, 2019
1a3a95c
Added list channels method to slack.rb
minipaige02 Sep 11, 2019
6c5aeca
Updated self.list for channels and corresponding cassetes.
minipaige02 Sep 11, 2019
e2d73e7
Added test for find user method.
minipaige02 Sep 12, 2019
b13fa09
added find_instance method and added tests for finding users by name …
geli-gel Sep 12, 2019
df4857e
Added tests to find a channel with the find_recipient method.
minipaige02 Sep 12, 2019
f9cff44
Added methods and tests to select user and select channel.
minipaige02 Sep 12, 2019
c1f0c8a
Began writing API error handling.
minipaige02 Sep 12, 2019
bf8a8ad
updated Recipient self.gets to raise SlackApiError on errored API res…
geli-gel Sep 12, 2019
c317d0d
added send_message to Recipient and added tests
geli-gel Sep 13, 2019
504008e
Added details methods for user and channel. Added show details functi…
minipaige02 Sep 13, 2019
51c83c4
added select_user, select_channel, and send_message to slack.rb
geli-gel Sep 13, 2019
3588db0
Added details functionality to slack.rb
minipaige02 Sep 13, 2019
2fb2f5a
Merged menu changes.
minipaige02 Sep 13, 2019
43098a4
formatting updates
geli-gel Sep 13, 2019
66ce941
moved send_message from slack.rb to Workspace
geli-gel Sep 13, 2019
f5af80e
moved methods around in slack.rb, added comment in workspace
geli-gel Sep 13, 2019
c85040b
updated User details method to pull in more information, and updated …
geli-gel Sep 13, 2019
2b77254
updated Channel details method to pull more info and added tests
geli-gel Sep 13, 2019
1842a8d
Refactored workspace send message method.
minipaige02 Sep 13, 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,6 @@ build-iPhoneSimulator/

# Ignore cassette files
/specs/cassettes/

# Ignore .DS_Store
.DS_Store

Choose a reason for hiding this comment

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

51 changes: 51 additions & 0 deletions lib/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require_relative 'recipient'

module SlackCLI
class Channel < Recipient
attr_reader :topic, :member_count

def initialize(slack_id:, name:, topic:, member_count:)
super(slack_id: slack_id, name: name)
@topic = topic
@member_count = member_count
end

def self.list
response = self.get("https://slack.com/api/channels.list")

channels = response["channels"].map do |channel|
slack_id = channel["id"]
name = channel["name"]
topic = channel["topic"]["value"]
member_count = channel["members"].length

SlackCLI::Channel.new(
slack_id: slack_id,
name: name,
topic: topic,
member_count: member_count
)
end

return channels
end

def details
key = ENV["API_TOKEN"]
response = HTTParty.get("https://slack.com/api/channels.info", query: {token: key , channel: @slack_id})
if response.keys.include? "error" || response["ok"] == false
raise SlackCLI::SlackApiError

Choose a reason for hiding this comment

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

It would be nice if you'd included what the error was in the message here.

Suggested change
raise SlackCLI::SlackApiError
raise SlackCLI::SlackApiError.new(response["error"])

end

purpose = response["channel"]["purpose"]["value"]
is_private = response["channel"]["is_private"] ? "true" : "false"

"Slack ID: #{slack_id}\n" +
"Name: #{name}\n" +
"Topic: #{topic}\n" +
"Member Count: #{member_count}\n" +
"Purpose: #{purpose}\n" +
"Is Private? #{is_private}"
end
end
end
55 changes: 55 additions & 0 deletions lib/recipient.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require 'httparty'
require 'dotenv'

Dotenv.load

module SlackCLI
class SlackApiError < StandardError; end
class Recipient
attr_reader :slack_id, :name

def initialize(slack_id:, name:)
@slack_id = slack_id
@name = name
end

def self.get(url)
key = ENV["API_TOKEN"]
response = HTTParty.get(url, query: {token: key })
if response.keys.include? "error" || response["ok"] == false
raise SlackCLI::SlackApiError
end

return response
end

def send_message(message)
# pull out key to be @key?
key = ENV["API_TOKEN"]
response = HTTParty.post(
"https://slack.com/api/chat.postMessage",
headers: {'Content-Type' => 'application/x-www-form-urlencoded'},
body: {
"token": key,
"channel": @slack_id,
"text": message
}
)

if response.keys.include? "error" || response["ok"] == false

Choose a reason for hiding this comment

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

You should be checking response.code here.

raise SlackCLI::SlackApiError.new("Message not sent due to error: #{response["error"]}")
else
return true

Choose a reason for hiding this comment

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

I appreciate what you're doing here but since this method raises the only thing it can ever return is true so I probably wouldn't bother with returning something.

end
end

def details
raise NotImplementedError.new("Details should be implemented in child class")
end

def self.list
raise NotImplementedError.new("Self.list should be implemented in child class")

Choose a reason for hiding this comment

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

Abstract methods! 🎉

end

end
end
105 changes: 102 additions & 3 deletions lib/slack.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,110 @@
#!/usr/bin/env ruby
require_relative 'workspace'
require 'table_print'
require 'terminal-table'

def main
puts "Welcome to the Ada Slack CLI!"
puts "\nWelcome to the Ada Slack CLI!"
workspace = SlackCLI::Workspace.new
channels_count = workspace.channels.length
users_count = workspace.users.length
puts "\n#{channels_count} channels and #{users_count} users loaded"

choice = ""
until choice == "7" || choice == "quit"
puts "\nWhat would you like to do?"
menu_options
print "Action: "
choice = gets.chomp.downcase

case choice
when "1","list users"
puts "\n"
list_users(workspace)

# TODO project
when "2","list channels"
puts "\n"
list_channels(workspace)

when "3","select user"
puts "Select User"
print "Please enter a Username or Slack ID: "
query = gets.chomp.downcase
query_result = workspace.select_user(query)
if query_result == nil
puts "\nUser with Username or Slack ID '#{query}' does not exist."
else
puts "\nUser '#{query_result.name}' selected"
end

when "4","select channel"
puts "Select Channel"
print "Please enter a Channel Name or Slack ID: "
query = gets.chomp.downcase
query_result = workspace.select_channel(query)

Choose a reason for hiding this comment

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

I'd have liked to have seen the error here handled with an exception and then rescued down below. That way the message could be constructed inside of select_channel and you wouldn't need the extra check below.

Plus, it could give you to opportunity to DRY up your code by putting all of your error handling in a single begin/rescue within your until wrapping your case.

if query_result == nil
puts "\nChannel with Name or Slack ID '#{query}' does not exist."
else
puts "\nChannel '#{query_result.name}' selected"
end

when "5","details"
if workspace.show_details == nil
puts "\nNo user or channel selected."
else
puts "\nDetails:"
puts "#{workspace.show_details}"
end

when "6","send message"
if workspace.selected == nil
puts "\nNo recipient selected to send message to."
else
puts "Send Message to '#{workspace.selected.name}'"
print "Please enter message text: "
message_text = gets.chomp

until message_text != ""
puts "No message entered."
print "Please enter message text: "
message_text = gets.chomp
end
if workspace.send_message(message_text)
puts "Message successfully sent"
end
end

when "7","quit"
break
else
puts "That option does not exist"
end

end

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

main if __FILE__ == $PROGRAM_NAME
def menu_options
numbered_options = [
["1", "list users"],
["2", "list channels"],
["3", "select user"],
["4", "select channel"],
["5", "details"],
["6", "send message"],
["7","quit"]
]
menu_table = Terminal::Table.new :headings => ["#", "Action"], :rows => numbered_options
puts menu_table
end

def list_users(workspace)
tp workspace.users, :slack_id, :name, :real_name
end

def list_channels(workspace)
tp workspace.channels, :slack_id, :name, :topic, :member_count
end

main if __FILE__ == $PROGRAM_NAME
48 changes: 48 additions & 0 deletions lib/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require_relative 'recipient'
require 'httparty'
require 'dotenv'

Dotenv.load


module SlackCLI
class User < Recipient
attr_reader :real_name

def initialize(slack_id:, name:, real_name:)
super(slack_id: slack_id, name: name)
@real_name = real_name
end

def self.list
response = self.get("https://slack.com/api/users.list")

users = response["members"].map do |member|
slack_id = member["id"]
name = member["name"]
real_name = member["real_name"]

SlackCLI::User.new(slack_id: slack_id, name: name, real_name: real_name)
end

return users
end

def details
key = ENV["API_TOKEN"]
response = HTTParty.get("https://slack.com/api/users.info", query: {token: key , user: @slack_id})

Choose a reason for hiding this comment

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

If you made self.get accept parameters then you could have avoided duplicating error handling.

if response.keys.include? "error" || response["ok"] == false
raise SlackCLI::SlackApiError
end

status = response["user"]["profile"]["status_text"]
is_bot = response["user"]["is_bot"] ? "true" : "false"

"Slack ID: #{slack_id}\n" +
"Name: #{name}\n" +
"Real Name: #{real_name}\n" +
"Status: #{status}\n" +
"Is Bot?: #{is_bot}"
end
end
end
48 changes: 48 additions & 0 deletions lib/workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require_relative 'user'
require_relative 'channel'

module SlackCLI
class Workspace
attr_reader :users, :channels
attr_accessor :selected

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

def find_instance(recipient_list, name_or_id)
instance = recipient_list.find do |recipient|
recipient.name.downcase == name_or_id.downcase ||
recipient.slack_id.downcase == name_or_id.downcase
end

return instance
end

def select_user(name_or_id)
user = find_instance(users, name_or_id)
@selected = user if user != nil

return @selected
end

def select_channel(name_or_id)
channel = find_instance(channels, name_or_id)
@selected = channel if channel != nil

return @selected
end

def show_details
selected ? selected.details : nil
end

def send_message(message_text)
@selected.send_message(message_text)
return true
end
end

end
Loading