-
Notifications
You must be signed in to change notification settings - Fork 27
Ports-Elise&Sav #4
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
base: master
Are you sure you want to change the base?
Changes from all commits
1f1590e
b973b4f
8cdcb30
78009f7
7bbe35a
7ed7582
dcf70d7
5eb884b
ef5210b
355aa6f
4300942
1e9a7da
fe963c2
17fbcae
43d65a7
ecada61
447dae2
deb6d79
a8baccb
c4d6e1b
646392e
1ca7c14
dd88f72
765c557
ea4fe70
088b575
15ff84c
6a4e40b
4e03f77
2845614
4c1de3e
07a989f
4021db8
2bc8f29
dee69e7
d7b3463
d876884
c4304e0
58bf152
acbcf99
fc5d71f
47c8dc7
e3b2bd1
93c9b05
1fc46a0
df97e06
53fd69a
34fb6a3
bc97377
1927a7d
0101c90
6156832
98fb396
43b9e78
3e0e6f4
561c19a
32126c8
12baef3
d68c46e
4233c79
5b3a477
388e58e
e670a19
5314af8
b48295a
774fdc6
3e77ac3
048e665
7de1697
4d29f21
40a7623
51e4fb7
bd5f45b
5dc28ba
73264e8
9e5a200
53b7859
3cd4230
4dbdd08
2096c3b
11d85f6
42335d0
f6d3580
601c70b
aeb79d9
b97ab69
39859fd
22c4fdb
46c9218
f3c3a19
87b86e4
aa01609
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| require "HTTParty" | ||
| require "dotenv" | ||
| Dotenv.load | ||
|
|
||
| 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 | ||
| 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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this method would be better named |
||
| 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 | ||
| 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 | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could also have an abstract method called |
||
| def details | ||
| raise NotImplementedError.new | ||
| end | ||
| end | ||
| end | ||
| 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 |
| 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 |
| 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| | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could also use |
||
| 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 | ||
| 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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment.
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.