Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
1f1590e
setting-up
qqdipps Mar 19, 2019
b973b4f
successfully verify the HTTP request
ChubbyCub Mar 19, 2019
8cdcb30
Merge branch 'master' of https://github.com/ChubbyCub/slack-cli
qqdipps Mar 19, 2019
78009f7
trying to verify token
qqdipps Mar 19, 2019
7bbe35a
VCR configure
ChubbyCub Mar 19, 2019
7ed7582
Merge branch 'master' of https://github.com/ChubbyCub/slack-cli
qqdipps Mar 19, 2019
dcf70d7
merge conflict
qqdipps Mar 19, 2019
5eb884b
test Recipient-initialize method
ChubbyCub Mar 19, 2019
ef5210b
Merge branch 'master' of https://github.com/ChubbyCub/slack-cli
ChubbyCub Mar 19, 2019
355aa6f
created recipient class and new test for vars
qqdipps Mar 19, 2019
4300942
passed test 0002 for intialize method
ChubbyCub Mar 19, 2019
1e9a7da
added webmock in test_helper
ChubbyCub Mar 20, 2019
fe963c2
added dotenv to test_helper.rb
ChubbyCub Mar 20, 2019
17fbcae
added test for details method in Recipient class
ChubbyCub Mar 20, 2019
43d65a7
details implemented for reciept class
qqdipps Mar 20, 2019
ecada61
added tests for initialize User class.
qqdipps Mar 20, 2019
447dae2
completed initialize for user class
ChubbyCub Mar 20, 2019
deb6d79
added test for details in user class
ChubbyCub Mar 20, 2019
a8baccb
added test for details, passed string type return
qqdipps Mar 20, 2019
c4d6e1b
completed details method, added return string format
ChubbyCub Mar 20, 2019
646392e
added tests for Channel#initialize
ChubbyCub Mar 20, 2019
1ca7c14
added class name
qqdipps Mar 20, 2019
dd88f72
added tests for instance vars
qqdipps Mar 20, 2019
765c557
completed constructor for channel class
ChubbyCub Mar 20, 2019
ea4fe70
added test for Channel#details
ChubbyCub Mar 20, 2019
088b575
added details method signature to channels
qqdipps Mar 20, 2019
15ff84c
added deatails formated expected test
qqdipps Mar 20, 2019
6a4e40b
complete channel class
ChubbyCub Mar 20, 2019
4e03f77
added respond test for api wrapper class
ChubbyCub Mar 20, 2019
2845614
method signatures for get_channels, get_users
qqdipps Mar 20, 2019
4c1de3e
added test for get_json method
ChubbyCub Mar 20, 2019
07a989f
added get_json method, updated method params
qqdipps Mar 20, 2019
4021db8
updated test to reflect design change
qqdipps Mar 20, 2019
2bc8f29
added more tests for get_json
ChubbyCub Mar 20, 2019
dee69e7
added helper method to build URL for slack api calls, still need rege…
qqdipps Mar 21, 2019
d7b3463
reverted back slackerror class to before debugging api exceptions
qqdipps Mar 21, 2019
d876884
completed get_channels and get_users in apiwrapper class
ChubbyCub Mar 21, 2019
c4304e0
added tests for post
qqdipps Mar 21, 2019
58bf152
completed post method in apiwrapper class
ChubbyCub Mar 21, 2019
acbcf99
added tests for checking invalid channel
qqdipps Mar 21, 2019
fc5d71f
added test for empty string post request
ChubbyCub Mar 21, 2019
47c8dc7
added test for invalid token
ChubbyCub Mar 21, 2019
e3b2bd1
added first test for create users in user
qqdipps Mar 21, 2019
93c9b05
fix error
ChubbyCub Mar 21, 2019
1fc46a0
debugger
qqdipps Mar 21, 2019
df97e06
added info for later tests
qqdipps Mar 21, 2019
53fd69a
added test for create_users
ChubbyCub Mar 21, 2019
34fb6a3
created user objects factory method
qqdipps Mar 21, 2019
bc97377
finished testing factory method in user
qqdipps Mar 21, 2019
1927a7d
added tests for channel
ChubbyCub Mar 21, 2019
0101c90
added factory method, testing complete. all good to go
qqdipps Mar 21, 2019
6156832
added test for Workspace#initialize
ChubbyCub Mar 21, 2019
98fb396
initialized begining of new class workspace.
qqdipps Mar 21, 2019
43b9e78
added test for instance vars.
qqdipps Mar 21, 2019
3e0e6f4
added more tests for initialize in workspace class
ChubbyCub Mar 21, 2019
561c19a
added tests for select channels
qqdipps Mar 21, 2019
32126c8
added select_channel method
ChubbyCub Mar 21, 2019
12baef3
added test for select_user
ChubbyCub Mar 21, 2019
d68c46e
merge
qqdipps Mar 21, 2019
4233c79
merge
qqdipps Mar 21, 2019
5b3a477
added test for list all
qqdipps Mar 21, 2019
388e58e
updated tests
qqdipps Mar 21, 2019
e670a19
merge
ChubbyCub Mar 21, 2019
5314af8
Merge branch 'master' of https://github.com/ChubbyCub/slack-cli
ChubbyCub Mar 21, 2019
b48295a
added list_all method
ChubbyCub Mar 21, 2019
774fdc6
added require message in workspace
ChubbyCub Mar 21, 2019
3e77ac3
add require message in user and channel
ChubbyCub Mar 21, 2019
048e665
added require message in user and channel
ChubbyCub Mar 21, 2019
7de1697
added httpary, dotenv in apiwrapper class
ChubbyCub Mar 21, 2019
4d29f21
added tests for list_all in workspace
ChubbyCub Mar 21, 2019
40a7623
added format to list_all(list)
qqdipps Mar 21, 2019
51e4fb7
added begin/rescue block
ChubbyCub Mar 21, 2019
bd5f45b
Merge branch 'master' of https://github.com/ChubbyCub/slack-cli
ChubbyCub Mar 21, 2019
5dc28ba
added tests for sending message, go
qqdipps Mar 21, 2019
73264e8
added send_message in workspace
ChubbyCub Mar 21, 2019
9e5a200
added test for details_for_selected in workspace
ChubbyCub Mar 21, 2019
53b7859
added details_for_selected method.
qqdipps Mar 22, 2019
3cd4230
added test for find_user in workspace class
ChubbyCub Mar 22, 2019
4dbdd08
merge
qqdipps Mar 22, 2019
2096c3b
merge
qqdipps Mar 22, 2019
11d85f6
uncomment invalid url test
ChubbyCub Mar 22, 2019
42335d0
Merge branch 'master' of https://github.com/ChubbyCub/slack-cli
qqdipps Mar 22, 2019
f6d3580
added logic for find_user and tests for find_channel,
qqdipps Mar 22, 2019
601c70b
completed find_channel for workspace
ChubbyCub Mar 22, 2019
aeb79d9
added back missing test
qqdipps Mar 22, 2019
b97ab69
fixed up main
qqdipps Mar 22, 2019
39859fd
working on CLI
ChubbyCub Mar 22, 2019
22c4fdb
completed select user command in CLI
ChubbyCub Mar 22, 2019
46c9218
added details and selected channel
qqdipps Mar 22, 2019
f3c3a19
completed CLI
ChubbyCub Mar 22, 2019
87b86e4
modularized main method
qqdipps Mar 22, 2019
aa01609
removed commented out code
qqdipps Mar 22, 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
53 changes: 53 additions & 0 deletions lib/apiwrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require "HTTParty"
require "dotenv"
Dotenv.load

Choose a reason for hiding this comment

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

I really like you having an API wrapper module here. It helps separate out the API from the rest of the app.

module Slack
module ApiWrapper
class SlackError < StandardError; end

URL_BASE = "https://slack.com/api/"

def self.get_channels
url_tail = "channels.list"
response = get_json(url_tail: url_tail)
return response
end

def self.get_users
url_tail = "users.list"
response = get_json(url_tail: url_tail)
return response
end

def self.get_json(url_tail:)
token = ENV["SLACK_API_KEY"]
query_params = {
"token": token,
}
response = HTTParty.get("#{URL_BASE}#{url_tail}", query: query_params)
if !response["ok"]
raise SlackError.new
end
return response
end

def self.post(text:, recipient:)
token = ENV["SLACK_API_KEY"]
response = HTTParty.post(
"#{URL_BASE}chat.postMessage",
headers: { "Content-Type" => "application/x-www-form-urlencoded" },
body: {
token: token,
channel: recipient,
text: text,
},
)
if response["ok"]
return true
else
raise ApiWrapper::SlackError, "Error when posting #{text} to #{recipient}, error: #{response.parsed_response["error"]}"
end
end
end
end
33 changes: 33 additions & 0 deletions lib/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require_relative "recipient"
require_relative "apiwrapper"

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

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

def details
return "Name: #{name}, \nID: #{id}, \nTopic: #{topic}, \nMember Count: #{member_count}"
end

def self.create_channels

Choose a reason for hiding this comment

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

Maybe this method would be better named list_channels.

channels = []
begin
response = ApiWrapper::get_channels
response["channels"].each do |channel|
channels << self.new(id: channel["id"],
name: channel["name"],
member_count: channel["num_members"],
topic: channel["topic"]["value"])
end
rescue ApiWrapper::SlackError
end
return channels
end
end
end
14 changes: 14 additions & 0 deletions lib/recipient.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Slack
class Recipient
attr_reader :name, :id

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

Choose a reason for hiding this comment

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

You could also have an abstract method called list which both user and Channel implement.

def details
raise NotImplementedError.new
end
end
end
103 changes: 99 additions & 4 deletions lib/slack.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,106 @@
#!/usr/bin/env ruby
require_relative "workspace"

def main
puts "Welcome to the Ada Slack CLI!"
workspace = Slack::Workspace.new
puts "\nWelcome to the Ada Slack CLI!"
puts "-------------------------------"
puts "\nWorkspace: Sav-Elise-API Project"
puts "Number of users: #{workspace.users.length}"
puts "Number of channels: #{workspace.channels.length}\n\n"
options = ["List Users", "List Channels", "Select User", "Select Channel", "Details", "Send Message", "Quit"]
while true
puts "--------OPTIONS--------"
puts options
print "\nPlease enter your command: "
input = gets.chomp.upcase
case input
when "LIST USERS"
list_users workspace
when "LIST CHANNELS"
list_channels workspace
when "SELECT USER"
select_user workspace
when "SELECT CHANNEL"
select_channel workspace
when "SEND MESSAGE"
send_message workspace
when "DETAILS"
details workspace
when "QUIT"
break
else
puts "Command not recognized. Try again!\n\n"
end
end
puts "Thank you for using the Ada Slack CLI"
end

def list_users(workspace)
list = workspace.list_all(list: workspace.users)
if list.empty?
puts "Unable to access users at this time."
else
puts "\n" + list + "\n"
end
end

# TODO project
def list_channels(workspace)
list = workspace.list_all(list: workspace.channels)
if list.empty?
puts "Unable to access channels at this time."
else
puts "\n" + list + "\n"
end
end

puts "Thank you for using the Ada Slack CLI"
def select_user(workspace)
print "Please enter user's name, real name or id: "
input = gets.chomp.upcase
user = workspace.find_user(input: input)
if user
workspace.select_recipient(recipient: user)
puts "Successfully upated selected user to #{user.name}.\n\n"
else
puts "#{input.capitalize} is not a valid user.\n\n"
end
end

def select_channel(workspace)
print "Please enter channel's name or id: "
input = gets.chomp.upcase
channel = workspace.find_channel(input: input)
if channel
workspace.select_recipient(recipient: channel)
puts "Successfully upated selected channel to #{channel.name}.\n\n"
else
puts "#{input.capitalize} is not a valid channel.\n\n"
end
end

def send_message(workspace)
recipient = workspace.selected
if recipient
puts "Please enter the message you want to send:"
message = gets.chomp
if message.empty?
puts "Error: No message to send.\n\n"
else
workspace.send_message(text: message)
puts "Message was sent to #{recipient.name}.\n\n"
end
else
puts "Error: first select channel or user.\n\n"
end
end

def details(workspace)
details = workspace.details_for_selected
if details.empty?
puts "Error: first select channel or user.\n\n"
else
puts "\n" + details + "\n\n"
end
end

main if __FILE__ == $PROGRAM_NAME
main if __FILE__ == $PROGRAM_NAME
31 changes: 31 additions & 0 deletions lib/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require_relative "recipient"
require_relative "apiwrapper"

module Slack
class User < Recipient
attr_reader :real_name

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

def details
return "Name: #{name}, \nReal Name: #{real_name}, \nID: #{id}"
end

def self.create_users
users = []
begin
response = ApiWrapper::get_users
response["members"].each do |user|
users << self.new(id: user["id"],
name: user["name"],
real_name: user["real_name"])
end
rescue ApiWrapper::SlackError
end
return users
end
end
end
61 changes: 61 additions & 0 deletions lib/workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require_relative "channel"
require_relative "user"

module Slack
class Workspace
attr_reader :users, :channels, :selected

def initialize
@users = User.create_users
@channels = Channel.create_channels
@selected = nil
end

def select_recipient(recipient:)
@selected = recipient
return true
end

def list_all(list:)
result = ""
list.each do |elem|
result << elem.details
result << "\n-----------------------\n"
end
return result
end

def send_message(text:)
return false unless selected
begin
ApiWrapper.post(text: text, recipient: selected.id)
rescue ApiWrapper::SlackError
return false
end
return true
end

def details_for_selected
return "" unless selected
return selected.details
end

def find_user(input:)
users.each do |user|

Choose a reason for hiding this comment

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

You could also use .find here.

if input == user.name.upcase || input == user.real_name.upcase || input == user.id.upcase
return user
end
end
return nil
end

def find_channel(input:)
channels.each do |channel|
if input == channel.name.upcase || input == channel.id.upcase
return channel
end
end
return nil
end
end
end
84 changes: 84 additions & 0 deletions specs/apiwrapper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require_relative "test_helper"

describe "Api Wrapper module" do
describe "Api Wrapper module" do

Choose a reason for hiding this comment

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

These two describes have the same text.

it "responds to get_users and get_channels" do
expect(Slack::ApiWrapper).must_respond_to :get_users
expect(Slack::ApiWrapper).must_respond_to :get_channels
end
end

describe "ApiWrapper.get_json" do
it "successfully gets a json object" do
url_tail = "users.list"
VCR.use_cassette("slack_api") do
response = Slack::ApiWrapper.get_json(url_tail: url_tail)
expect(response).must_be_instance_of HTTParty::Response
end
end

it "raise an error if an invalid url is used" do
url_tail = "abc"
VCR.use_cassette("slack_api") do
expect {
Slack::ApiWrapper.get_json(url_tail: url_tail)
}.must_raise Slack::ApiWrapper::SlackError
end
end

it "raise an error when an invalid token is used" do
VCR.use_cassette("slack_api") do
real_token = ENV["SLACK_API_KEY"]
ENV["SLACK_API_KEY"] = "NOT_REAL_TOKEN"
expect {
Slack::ApiWrapper.post(text: "Test message with invalid key", recipient: "general")
}.must_raise Slack::ApiWrapper::SlackError
ENV["SLACK_API_KEY"] = real_token
end
end
end

describe "ApiWrapper.get_channels" do
it "will return a Response object" do
VCR.use_cassette("slack_api") do
response = Slack::ApiWrapper.get_channels

Choose a reason for hiding this comment

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

You should also verify that it returns the right format of data.

expect(response).must_be_instance_of HTTParty::Response
end
end
end

describe "ApiWrapper.post" do
it "can send a valid message to a channel" do
VCR.use_cassette("slack_api") do
response = Slack::ApiWrapper.post(text: "test text", recipient: "random")
expect(response).must_equal true
end
end

it "can send a valid message to a user" do
VCR.use_cassette("slack_api") do
user_id = "UH2RH81RA"
response = Slack::ApiWrapper.post(text: "test text", recipient: user_id)
expect(response).must_equal true
end
end

it "will raise exception if invalid channel used" do
VCR.use_cassette("slack_api") do
user_id = "Noarealid234"
expect {
Slack::ApiWrapper.post(text: "test text", recipient: user_id)
}.must_raise Slack::ApiWrapper::SlackError
end
end

it "will raise exception if no text is provided" do
VCR.use_cassette("slack_api") do
user_id = "UH2RH81RA"
expect {
Slack::ApiWrapper.post(text: "", recipient: user_id)
}.must_raise Slack::ApiWrapper::SlackError
end
end
end
end
Loading