Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions lib/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'httparty'
require 'dotenv'
require_relative 'recipient'
require 'table_print'

class Channel < Recipient
attr_reader :name, :slack_id, :topic, :member_count

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

def self.endpoint_path
return 'conversations.list'
end

def self.response_key
return 'channels'
end

def self.from_response_hash(record_hash)
return Channel.new(record_hash['name'], record_hash['id'], record_hash['topic']['value'], record_hash['num_members'])
end
Comment on lines +23 to +25

Choose a reason for hiding this comment

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

Love this method!


def to_details
return "-- Details --\nName: #{name}, Slack ID: #{slack_id}, Topic: #{topic}, Member Count: #{member_count.to_s}"
end
end
39 changes: 39 additions & 0 deletions lib/recipient.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require 'dotenv'

class Recipient

Choose a reason for hiding this comment

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

I love the use of template methods here. Nice work!

class InvalidAPIError < StandardError; end

attr_reader :name, :slack_id

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

def self.run_get_request(path)
sleep(0.5)
base_url = 'https://slack.com/api/'
method_url = base_url + path

response = HTTParty.get(method_url, query: {
token: ENV['SLACK_TOKEN'],
format: 'json'
}
)

unless response.code == 200
raise InvalidAPIError, "Error! Status code: #{response.code}"
end

unless response["ok"]
raise InvalidAPIError, "#{response["error"]}"
end

return response
end

def self.list_all
response = self.run_get_request(endpoint_path)
return response[response_key].map { |record_hash| from_response_hash(record_hash) }
end
end
76 changes: 73 additions & 3 deletions lib/slack.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,80 @@
#!/usr/bin/env ruby
require 'httparty'
require 'dotenv'
require 'awesome_print'
require 'table_print'
require_relative 'user'
require_relative 'channel'
require_relative 'workspace'
Dotenv.load

def driver(workspace)

while true
puts "\nChoose: list users | list channels | select user | select channel | show details | send message | quit"

user_input = gets.chomp

exit if user_input.downcase == 'quit'

case user_input
when 'list users'
tp User.list_all, 'name', 'slack_id', 'real_name'
when'list channels'
tp Channel.list_all, 'name', 'slack_id', 'topic', 'member_count'
when 'select user'
print 'Which user would you like to select? '
user_to_select = gets.chomp
if workspace.user_doesnt_exist?(user_to_select)
puts "Invalid user name. What would you like to do?"
driver(workspace)
elsif workspace.select_user(user_to_select)
print "Successfully selected #{workspace.return_selected.name}!"
end
when 'select channel'
print 'Which channel would you like to select? '
channel_to_select = gets.chomp
if workspace.channel_doesnt_exist?(channel_to_select)
puts "Invalid channel name. What would you like to do?"
driver(workspace)
elsif workspace.select_channel(channel_to_select)
print "Successfully selected #{workspace.return_selected.name}!"
end
when 'show details'
if workspace.no_selection? # would like to refactor this for DRY
puts "Nothing was selected!"
driver(workspace)
else
print workspace.to_details
end
when 'send message'
if workspace.no_selection?
puts "Nothing was selected!"
driver(workspace)
else
puts "What would you like to say?"
user_response = gets.chomp
selected_slack_id = workspace.return_selected.slack_id
workspace.send_message(selected_slack_id, user_response)
end
else
puts "Invalid entry!"
end
end
end

def main
puts "Welcome to the Ada Slack CLI!"

unless ENV["SLACK_TOKEN"]
puts "Could not load API key"
exit
end

workspace = Workspace.new
puts "Welcome to the Ada Slack CLI! 'quit' to quit"
puts "There are #{User.list_all.length} users."
puts "There are #{Channel.list_all.length} channels."

# TODO project
driver(workspace)

puts "Thank you for using the Ada Slack CLI"
end
Expand Down
30 changes: 30 additions & 0 deletions lib/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'httparty'
require 'dotenv'
require_relative 'recipient'
require 'table_print'
Dotenv.load

class User < Recipient
attr_reader :name, :slack_id, :real_name

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

def self.endpoint_path
return 'users.list'
end

def self.response_key
return 'members'
end

def self.from_response_hash(record_hash)
return User.new(record_hash['name'], record_hash['id'], record_hash['real_name'])
end

def to_details
return "-- Details -- \nName: #{name}, Slack ID: #{slack_id}, Real Name: #{real_name}"
end
end
92 changes: 92 additions & 0 deletions lib/workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
require 'httparty'
require 'dotenv'
require 'awesome_print'
require 'table_print'
require_relative 'user'
require_relative 'channel'
require_relative 'recipient'
Dotenv.load

class Workspace < Recipient
class InvalidAPIError < StandardError; end

attr_reader :users, :channels, :selected

def initialize
@users = User.list_all
@channels = Channel.list_all
@selected = nil

validate_user?(@users)
validate_channel?(@channels)
end

def validate_user?(users)
raise ArgumentError.new, "Sorry! Users couldn't be loaded" if users.nil?
raise ArgumentError.new, "Sorry! There are 0 users" if users.length.zero?
end

def validate_channel?(channels)
raise ArgumentError.new, "Sorry! channels couldn't be loaded" if channels.nil?
raise ArgumentError.new, "Sorry! There are 0 channels" if channels.length.zero?
end

def select_user(user_to_select)
if @users.any? { |user| user.name == user_to_select }
@selected = @users.find { |user| user.name == user_to_select }
elsif @users.any? { |user| user.slack_id == user_to_select }
@selected = @users.find { |user| user.slack_id == user_to_select }
end
return @selected
end

def select_channel(channel_to_select)
if @channels.any? { |channel| channel.name == channel_to_select }
@selected = @channels.find { |channel| channel.name == channel_to_select }
elsif @channels.any? { |channel| channel.slack_id == channel_to_select }
@selected = @channels.find { |channel| channel.slack_id == channel_to_select }
end
return @selected
end

def return_selected
return @selected
end

def to_details
return @selected.to_details
end

def no_selection?
@selected.nil?
end

def send_message(selected_slack_id, user_response)
url = "https://slack.com/api/chat.postMessage"

response = HTTParty.post(url,
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
body: {
token: ENV["SLACK_TOKEN"],
channel: selected_slack_id,
text: user_response
})

unless response.code == 200
raise InvalidAPIError, "Error! Status code: #{response.code}"
end

unless response["ok"]
raise InvalidAPIError, "Your message #{user_response} did not go through. Error: #{response["error"]}"
end
return true
end
Comment on lines +64 to +83

Choose a reason for hiding this comment

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

I would suggest adding send_message to the recipient class thus removing responsibility for dealing with the API from the workspace class. Separating concerns.


def channel_doesnt_exist?(channel_to_select)
return true unless (@channels.any? { |channel| channel.name == channel_to_select || channel.slack_id == channel_to_select })
end

def user_doesnt_exist?(user_to_select)
return true unless (@users.any? { |user| user.name == user_to_select || user.slack_id == user_to_select })
end
end
1 change: 1 addition & 0 deletions response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"ok":true,"members":[{"id":"USLACKBOT","team_id":"T01C6RMKV0U","name":"slackbot","deleted":false,"color":"757575","real_name":"Slackbot","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Slackbot","real_name_normalized":"Slackbot","display_name":"Slackbot","display_name_normalized":"Slackbot","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"sv41d8cd98f0","always_active":true,"first_name":"slackbot","last_name":"","image_24":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_24.png","image_32":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_32.png","image_48":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_48.png","image_72":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_72.png","image_192":"https:\/\/a.slack-edge.com\/80588\/marketing\/img\/avatars\/slackbot\/avatar-slackbot.png","image_512":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_512.png","status_text_canonical":"","team":"T01C6RMKV0U"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":0},{"id":"U01C0LNKLEN","team_id":"T01C6RMKV0U","name":"earth_emily_api_proje","deleted":false,"color":"e7392d","real_name":"Earth - Emily - API Project","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Earth - Emily - API Project","real_name_normalized":"Earth - Emily - API Project","display_name":"","display_name_normalized":"","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"gef282f65beb","api_app_id":"A01C0SBD2SF","always_active":false,"bot_id":"B01CD9S36V7","image_24":"https:\/\/secure.gravatar.com\/avatar\/ef282f65beb64d7cf4cbcc11029a2a0a.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0003-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/ef282f65beb64d7cf4cbcc11029a2a0a.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0003-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/ef282f65beb64d7cf4cbcc11029a2a0a.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0003-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/ef282f65beb64d7cf4cbcc11029a2a0a.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0003-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/ef282f65beb64d7cf4cbcc11029a2a0a.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0003-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/ef282f65beb64d7cf4cbcc11029a2a0a.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0003-512.png","status_text_canonical":"","team":"T01C6RMKV0U"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"is_app_user":false,"updated":1601948016},{"id":"U01CD92U2SD","team_id":"T01C6RMKV0U","name":"annatokar","deleted":false,"color":"9f69e7","real_name":"annatokar","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"annatokar","real_name_normalized":"annatokar","display_name":"","display_name_normalized":"","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g532f6d35c40","image_24":"https:\/\/secure.gravatar.com\/avatar\/532f6d35c4031ef0dab63b53f23e95ae.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0015-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/532f6d35c4031ef0dab63b53f23e95ae.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0015-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/532f6d35c4031ef0dab63b53f23e95ae.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0015-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/532f6d35c4031ef0dab63b53f23e95ae.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0015-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/532f6d35c4031ef0dab63b53f23e95ae.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0015-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/532f6d35c4031ef0dab63b53f23e95ae.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0015-512.png","status_text_canonical":"","team":"T01C6RMKV0U"},"is_admin":true,"is_owner":true,"is_primary_owner":true,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":1601946759},{"id":"U01CD9539FT","team_id":"T01C6RMKV0U","name":"emnagai89","deleted":false,"color":"4bbe2e","real_name":"Emily Nagai","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Emily Nagai","real_name_normalized":"Emily Nagai","display_name":"Emily Nagai","display_name_normalized":"Emily Nagai","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"27eeeb533273","image_original":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_original.png","is_custom_image":true,"image_24":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_24.png","image_32":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_32.png","image_48":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_48.png","image_72":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_72.png","image_192":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_192.png","image_512":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_512.png","image_1024":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1405593945349_27eeeb533273919ad28c_1024.png","status_text_canonical":"","team":"T01C6RMKV0U"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":1601946934,"has_2fa":false},{"id":"U01CD9SBB9P","team_id":"T01C6RMKV0U","name":"earth_anya_api_projec","deleted":false,"color":"3c989f","real_name":"Earth - Anya - API Project","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Earth - Anya - API Project","real_name_normalized":"Earth - Anya - API Project","display_name":"","display_name_normalized":"","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g4befea1e0e7","api_app_id":"A01C0S92KBM","always_active":false,"bot_id":"B01BKUB286T","image_24":"https:\/\/secure.gravatar.com\/avatar\/4befea1e0e71664dc4271a1dd0d3136d.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0012-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/4befea1e0e71664dc4271a1dd0d3136d.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0012-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/4befea1e0e71664dc4271a1dd0d3136d.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0012-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/4befea1e0e71664dc4271a1dd0d3136d.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0012-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/4befea1e0e71664dc4271a1dd0d3136d.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0012-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/4befea1e0e71664dc4271a1dd0d3136d.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0012-512.png","status_text_canonical":"","team":"T01C6RMKV0U"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"is_app_user":false,"updated":1601948031}],"cache_ts":1602023807,"response_metadata":{"next_cursor":""}}
Loading