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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ build-iPhoneSimulator/

# Ignore cassette files
/specs/cassettes/
.DS_Store
24 changes: 24 additions & 0 deletions lib/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'table_print'
require "httparty"
require "dotenv"

class Channel
attr_reader :name, :id, :topic, :member_count
# @topic = topic
# @member_count = member_count

def initialize(channel_map)
@id = channel_map['id']
@topic = channel_map['topic']['value']
@member_count = channel_map['num_members']
@name = channel_map['name']
end

# def details
# return "slack id: #{@id} #{@topic} member count: #{@member_count}"
# end

def to_s
"Name:#{@name},Topic:#{@topic},Member count :#{@member_count},Slack ID: #{@id}"
end
end
24 changes: 24 additions & 0 deletions lib/recipient.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'dotenv'
require 'httparty'
Dotenv.load

class Recipient
@slack_id = slack_id
@name = name

def send_message(message)
#code here
end

# def self.get(url, params)
# #code here
# end

def details
raise 'Please implement me'
end

def self.list
raise 'Please implement me'
end
end
60 changes: 60 additions & 0 deletions lib/slack-cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require_relative "./workspace"

class SlackCLI
def initialize(api_token)
@commands = {
'list users' => self.method(:list_users),
'list channels' => self.method(:list_channels),
'select user' => self.method(:select_user),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is a pretty advanced technique for organizing these method calls. It works, and is arguably much cleaner than a big switch statement, but it's a little concerning that you spent time figuring out how to do this but didn't complete all the waves.

In general, it is wise to do it the way you know first, then refactor it to the fancy way if you have time later. That's especially true if it's something not connected to the learning goals of the assignment.

If this code or the idea for it came from a tutor, please pass along this feedback!

'select channel' => self.method(:select_channel),
'exit' => self.method(:quit),
'quit' => self.method(:quit),
}
@time_to_go = false
@workspace = Workspace.new(api_token)
end

def quit
@time_to_go = true
end

def list_users
puts @workspace.users
end

def list_channels
puts @workspace.channels
end

def select_user
print "which user? "
user = gets.chomp
selected_user = @workspace.select_user(user)
if selected_user.nil?
puts "thats not a user try again"
end
end

def select_channel
print "which channel? "
channel = gets.chomp
selected_channel = @workspace.select_channel(channel)
if selected_channel.nil?
puts "thats not a user try again"
end
end

def run
while !@time_to_go do
puts "Please enter one of the available commands: #{@commands.keys}"
print 'Command: '
command = gets.chomp
if @commands.key? command
@commands[command].call
else
puts 'You silly goose! That is no command!'
end
end
puts 'Toodles!'
end
end
11 changes: 0 additions & 11 deletions lib/slack.rb

This file was deleted.

22 changes: 22 additions & 0 deletions lib/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class User
attr_accessor :username, :real_name, :id
def initialize(user_map)
@username = user_map['name']
@real_name = user_map['real_name']
@id = user_map['id']
# @status_text = user_map['status_text']
# @status_emoji = user_map['status_emoji']
end

# def details do
# #code here
# end
#
# def self.list
# #code here
# end

def to_s
"Username: #{@username}, Real name: #{@real_name}, Slack ID: #{@id}"
end
end
65 changes: 65 additions & 0 deletions lib/workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require 'httparty'
require 'dotenv'
require_relative './user'
require_relative './channel'

# response = HTTParty.get('https://slack.com/api/channels.list?token=xoxp-my-great-key&pretty=1')
# puts response.body, response.code, response.message, response.headers.inspect

# https://slack.com/api/channels.list?token=xoxp-my-great-key&pretty=1
class Workspace
include HTTParty
base_uri 'slack.com/api'

def initialize(api_token)
@options = { query: { token: api_token, pretty: 1 } }
end

def channels
response = self.class.get('/channels.list', @options).parsed_response
raise 'Failed to get channels' unless response['ok']

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

When you raise an exception you should provide an exception type! Otherwise you get a RuntimeError, which is pretty generic. Defining a custom exception type like SlackApiError might be a good choice here.

channels = response['channels'].map do |channel_map|
Channel.new(channel_map)
end
channels
end

def users
response = self.class.get('/users.list', @options).parsed_response
raise 'Failed to get users' unless response['ok']

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

For this method (and channels above), I have two comments:

  • Since there's a lot of code here that has to do with creating users, this code might fit well as a class method on User
  • Since API calls are expensive, it might make sense to do this work once in the constructor, and save the results in instance variables

The end result might look like this:

# user.rb
class User
  def self.list
    # move the code currently in Workspace#users to here
  end
  # ...
end

# workspace.rb
class Workspace
  attr_reader :channels, :users
  def initialize
    @channels = Channel.list
    @users = User.list
    # ...
  end
  # ...
end

users = response['members'].map do |user_map|
User.new(user_map)
end
users
end

def select_channel(selected_channel)
channels.each do |channel|
if channel.name == selected_channel || channel.id == selected_channel
@selected = channel
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ruby's .find enumerable method might be helpful to clarify this code.

return channel
end
end
nil
end

def select_user(selected_user)
users.each do |user|
if user.username == selected_user || user.id == selected_user
@selected = user
return user
end
end
nil
end

# def show_details(details)
# #code
# end

# def send_message
# #code
# end
end
9 changes: 9 additions & 0 deletions slack-cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#! /usr/bin/env ruby
#shebang line.
require "dotenv"
require_relative 'lib/slack-cli'

Dotenv.load('.env')
api_token = ENV['SLACK_API_TOKEN']
cli = SlackCLI.new(api_token)
cli.run()
Empty file added specs/channel_spec.rb
Empty file.
1 change: 1 addition & 0 deletions specs/recipient_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

2 changes: 1 addition & 1 deletion specs/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
VCR.configure do |config|
config.cassette_library_dir = "specs/cassettes"
config.hook_into :webmock
end
end
Empty file added specs/user_spec.rb
Empty file.
79 changes: 79 additions & 0 deletions specs/workspace_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
require "dotenv"

require_relative './test_helper'
require_relative '../lib/workspace'

describe "workspace" do
before do
Dotenv.load('.env')
api_token = ENV['SLACK_API_TOKEN']
@workspace = Workspace.new(api_token)
end

describe "channels" do
it "must be instance of array" do
VCR.use_cassette("good channels") do
channels = @workspace.channels
expect(channels).must_be_kind_of Array
end
end
end

describe "select_channel" do
it "finds a chanel by channel name" do
VCR.use_cassette("select channel by name") do
# expect{workspace.select_user}.must_be
# arrange
channel_name = "random"
# act
selected_channel = @workspace.select_channel(channel_name)
# assert
expect(selected_channel.name).must_equal 'random'
end
end

it "finds a channel by id" do
VCR.use_cassette("select channel by id") do
id = "CH36Q9YKX"
selected_channel = @workspace.select_channel(id)
expect(selected_channel.id).must_equal 'CH36Q9YKX'
end
end

describe "users" do
it "must be instance of array" do
VCR.use_cassette("good users") do
users = @workspace.users
expect(users).must_be_kind_of Array
end
end

it "must raise exception for bad response" do
workspace = Workspace.new('badapitoken')
VCR.use_cassette("bad channels") do
expect{workspace.channels}.must_raise RuntimeError
end
end
end

describe "select_user" do
it "finds a user by username" do
VCR.use_cassette("select user") do
# arrange
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing test cases for this (and select_channel above):

  • User does not exist
  • What happens to a previously selected user if you try to select a user that D.N.E.?

user_name = "kateannnichols"
# act
selected_user = @workspace.select_user(user_name)
# assert
expect(selected_user.username).must_equal 'kateannnichols'
end
end
it "finds a user by id" do
VCR.use_cassette("select user") do
id = "UH2SA7YJE"
selected_user = @workspace.select_user(id)
expect(selected_user.id).must_equal 'UH2SA7YJE'
end
end
end
end
end