diff --git a/lib/channel.rb b/lib/channel.rb new file mode 100644 index 00000000..278999ec --- /dev/null +++ b/lib/channel.rb @@ -0,0 +1,26 @@ +require "pry" +require "httparty" +require_relative "recipient" + +module SlackAPI + class SlackError < StandardError; end + + class Channel < Recipient + BASE_URL = "https://slack.com/api/" + + def self.list_channels + response = Recipient.get("channels.list") + + channel_list = [] + + if response["ok"] != true + raise SlackAPI::SlackError, "There was an error. The error message is #{response["error"]}" + else + response["channels"].each do |channel| + channel_list << { "name" => channel["name"], "topic" => channel["topic"]["value"], "member count" => channel["members"].length, "id" => channel["id"] } + end + end + return channel_list + end + end #end of class +end #end of module diff --git a/lib/recipient.rb b/lib/recipient.rb new file mode 100644 index 00000000..45321edc --- /dev/null +++ b/lib/recipient.rb @@ -0,0 +1,31 @@ +module SlackAPI + class Recipient + BASE_URL = "https://slack.com/api/" + + def self.get(sub_url) + query = { + token: ENV["SLACK_API_TOKEN"], + } + + response = HTTParty.get("#{BASE_URL}#{sub_url}", query: query) + + return response + end + + def send_msg(recipient, text) + response = HTTParty.post("#{BASE_URL}chat.postMessage", + headers: {"Content-Type" => "application/x-www-form-urlencoded"}, + body: { + token: ENV["SLACK_API_TOKEN"], + channel: recipient, + text: text, + }) + + if response["ok"] == false + raise SlackAPI::SlackError, "Error when posting #{text} to #{recipient}, error #{response["error"]}" + else + return true + end + end + end +end diff --git a/lib/slack.rb b/lib/slack.rb index 960cf2f7..2a245b2f 100755 --- a/lib/slack.rb +++ b/lib/slack.rb @@ -1,11 +1,74 @@ #!/usr/bin/env ruby +require_relative "user" +require_relative "channel" +require_relative "workspace" +require "httparty" +require "table_print" +require "dotenv" +Dotenv.load def main puts "Welcome to the Ada Slack CLI!" + puts "The workspace has #{SlackAPI::Channel.list_channels.length} channels and #{SlackAPI::User.list_users.length} users" + ask_again = "Select an option: \n1. list users \n2. list channels \n3. select user \n4. select channel \n5. details (select user or channel first)\n6. send message (select user or channel first) \n7. quit" + puts ask_again + response = gets.chomp.downcase - # TODO project - - puts "Thank you for using the Ada Slack CLI" + until response == "7" || response == "quit" + if response == "list users" || response == "1" + tp SlackAPI::User.list_users, "name", "real name", "slack id" + puts ask_again + response = gets.chomp.downcase + elsif response == "list channels" || response == "2" + tp SlackAPI::Channel.list_channels, "name", "topic", "member count", "id" + puts ask_again + response = gets.chomp.downcase + elsif response == "select user" || response == "3" + select_response = "select user" + puts "What is the user id or Slack name?" + identifier = gets.chomp.downcase + user = SlackAPI::Workspace.new + selected_recipient = user.select_user(identifier) + if selected_recipient == "" + puts "There is no user with that identifier" + end + puts ask_again + response = gets.chomp.downcase + elsif response == "select channel" || response == "4" + select_response = "select channel" + puts "What is the user id or Slack name?" + identifier = gets.chomp.downcase + channel = SlackAPI::Workspace.new + selected_recipient = channel.select_channel(identifier) + if selected_recipient == "" + puts "There is no channel with that identifier" + end + puts ask_again + response = gets.chomp.downcase + elsif response == "details" || response == "5" + if select_response == "select user" + details = user.see_user_details(selected_recipient) + tp details, "name", "real name", "slack id" + puts ask_again + response = gets.chomp.downcase + elsif select_response == "select channel" + details = channel.see_channel_details(selected_recipient) + tp details, "name", "topic", "member count", "id" + puts ask_again + response = gets.chomp.downcase + else + puts "Select a user or channel first" + puts ask_again + response = gets.chomp.downcase + end + elsif response == "send message" || response == "6" + puts "What would you like to say?" + text = gets.chomp.downcase + msg = SlackAPI::Recipient.new.send_msg(selected_recipient, text) + puts ask_again + response = gets.chomp.downcase + end + end end -main if __FILE__ == $PROGRAM_NAME \ No newline at end of file +main if __FILE__ == $PROGRAM_NAME diff --git a/lib/user.rb b/lib/user.rb new file mode 100644 index 00000000..528b69a2 --- /dev/null +++ b/lib/user.rb @@ -0,0 +1,26 @@ +require "pry" +require "httparty" +require_relative "recipient" + +module SlackAPI + class SlackError < StandardError; end + + class User < Recipient + BASE_URL = "https://slack.com/api/" + + def self.list_users + response = Recipient.get("users.list") + + user_list = [] + + if response["ok"] + response["members"].each do |member| + user_list << {"name" => member["name"], "real name" => member["real_name"], "slack id" => member["id"]} + end + else + raise SlackAPI::SlackError, "There was an error. The error message is #{response["error"]}" + end + return user_list + end + end # end of class +end # end of module diff --git a/lib/verification.rb b/lib/verification.rb new file mode 100644 index 00000000..b0c8d6dd --- /dev/null +++ b/lib/verification.rb @@ -0,0 +1,19 @@ +require "httparty" +require "pry" +require "dotenv" +Dotenv.load + +BASE_URL = "https://slack.com/api/channels.list" +query = { + token: ENV["SLACK_API_TOKEN"], +} + +response = HTTParty.get(BASE_URL, query: query) + +response["channels"].each do |channel| + print channel["name"] +end +# code snips to save: +# puts channel["topic"]["value"] # gets topic +# puts channel["members"].length # gets # of members +# puts channel["id"] # gets slack id for channel diff --git a/lib/workspace.rb b/lib/workspace.rb new file mode 100644 index 00000000..a33ac701 --- /dev/null +++ b/lib/workspace.rb @@ -0,0 +1,71 @@ +require_relative "recipient" +require "httparty" + +module SlackAPI + class Workspace + def select_channel(identifier) + response = Recipient.get("channels.list") + + selected_channel = "" + response["channels"].each do |channel| + if channel["id"] == identifier + selected_channel = identifier + elsif channel["name"] == identifier + selected_channel = identifier + end + end + if selected_channel == "" + raise SlackAPI::SlackError, "That is not a vaild channel" + end + return selected_channel + end + + def see_channel_details(identifier) + response = Recipient.get("channels.list") + + channel_details = [] + + response["channels"].each do |channel| + if channel["id"] == identifier || channel["name"] == identifier + channel_details << { "name" => channel["name"], "topic" => channel["topic"]["value"], "member count" => channel["members"].length, "id" => channel["id"] } + return channel_details + end + end + end + + def select_user(identifier) + response = Recipient.get("users.list") + + selected_user = "" + + response["members"].each do |member| + if member["id"] == identifier + selected_user = member["id"] + elsif member["name"] == identifier + selected_user = member["id"] + end + end + if selected_user == "" + raise SlackAPI::SlackError, "That is not a valid user" + end + return selected_user + end + + def see_user_details(identifier) + response = Recipient.get("users.list") + + user_details = [] + + response["members"].each do |member| + if member["id"] == identifier || member["name"] == identifier + user_details << + { "name" => member["name"], + "real name" => member["real_name"], + "slack id" => member["id"] } + + return user_details + end + end + end + end # end of class +end # end of module diff --git a/specs/channel_spec.rb b/specs/channel_spec.rb new file mode 100644 index 00000000..d74d3907 --- /dev/null +++ b/specs/channel_spec.rb @@ -0,0 +1,55 @@ +require_relative "test_helper" + +describe "self.list" do + it "list all channels" do + VCR.use_cassette("list_channels") do + response = SlackAPI::Channel.list_channels + + expect(response).wont_be_nil + expect(response[0]).must_equal "name" => "general", "topic" => "Company-wide announcements", "member count" => 2, "id" => "CH2SKTKPC" + expect(response.length).must_equal 3 + end + end + it "will raise an error if given an invalid key" do + real_token = ENV["SLACK_API_TOKEN"] + ENV["SLACK_API_TOKEN"] = "NOT_REAL_TOKEN" + + VCR.use_cassette("list_channels_2") do + error = expect { + SlackAPI::Channel.list_channels + }.must_raise SlackAPI::SlackError + expect(error.message).must_equal "There was an error. The error message is invalid_auth" + end + + ENV["SLACK_API_TOKEN"] = real_token + end +end + +describe "send_msg" do + it "sends a message to selected channel" do + channel = SlackAPI::Channel.new() + VCR.use_cassette("send_msg") do + msg = channel.send_msg("CH2SKTKPC", "This is a test message!") + expect(msg).must_equal true + end + end + + it "generates an error if given an invalid channel" do + VCR.use_cassette("send_msg") do + expect { + SlackAPI::Channel.new.send_msg("bogus", "Test message") + }.must_raise SlackAPI::SlackError + end + end + + it "will raise an error if given an empty message" do + VCR.use_cassette("send_msg") do + error = expect { + SlackAPI::Channel.new.send_msg("general", + "") + }.must_raise SlackAPI::SlackError + + # expect(error.message).must_equal "Error when posting to ports-api-testing, error: no_text" + end + end +end diff --git a/specs/test_helper.rb b/specs/test_helper.rb index 81ccd06b..dc312462 100644 --- a/specs/test_helper.rb +++ b/specs/test_helper.rb @@ -1,15 +1,33 @@ -require 'simplecov' +require "simplecov" SimpleCov.start +require "dotenv" +Dotenv.load -require 'minitest' -require 'minitest/autorun' -require 'minitest/reporters' -require 'minitest/skip_dsl' -require 'vcr' +require "httparty" +require "minitest" +require "minitest/autorun" +require "minitest/reporters" +require "minitest/skip_dsl" +require "webmock/minitest" +require "vcr" + +require_relative "../lib/channel.rb" +require_relative "../lib/slack.rb" +require_relative "../lib/user.rb" +require_relative "../lib/recipient.rb" +require_relative "../lib/workspace.rb" Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new VCR.configure do |config| config.cassette_library_dir = "specs/cassettes" config.hook_into :webmock -end \ No newline at end of file + config.default_cassette_options = { + :record => :new_episodes, # record new data when we don't have it yet + :match_requests_on => [:method, :uri, :body], # The http method, URI and body of a request all need to match + } + # Don't leave our token lying around in a cassette file. + config.filter_sensitive_data("") do + ENV["SLACK_API_TOKEN"] + end +end diff --git a/specs/user_spec.rb b/specs/user_spec.rb new file mode 100644 index 00000000..e960c6da --- /dev/null +++ b/specs/user_spec.rb @@ -0,0 +1,53 @@ +require_relative "test_helper" +describe SlackAPI do + describe "self.list" do + it "list all users" do + VCR.use_cassette("list_users") do + response = SlackAPI::User.list_users + expect(response).wont_be_nil + expect(response[2]).must_equal "name" => "aribray", "real name" => "Ariana Bray", + "slack id" => "UH3UT3SJK" + expect(response.length).must_equal 3 + end + end + it "will raise an error if given an invalid key" do + real_token = ENV["SLACK_API_TOKEN"] + ENV["SLACK_API_TOKEN"] = "NOT_REAL_TOKEN" + + VCR.use_cassette("list_users_2") do + error = expect { + SlackAPI::User.list_users + }.must_raise SlackAPI::SlackError + expect(error.message).must_equal "There was an error. The error message is invalid_auth" + end + + ENV["SLACK_API_TOKEN"] = real_token + end + end + + describe "send_usr_msg" do + it "sends a message to selected user" do + VCR.use_cassette("send_usr_msg") do + msg = SlackAPI::User.new.send_msg("UH3UT3SJK", "This is a test message!") + expect(msg).must_equal true + end + end + + it "generates an error if given an invalid user" do + VCR.use_cassette("send_usr_msg") do + expect { + SlackAPI::User.new.send_msg("bob's your uncle", "Test message") + }.must_raise SlackAPI::SlackError + end + end + + it "will raise an error if given an empty message" do + VCR.use_cassette("send_usr_msg") do + error = expect { + SlackAPI::User.new.send_msg("UH3UT3SJK", + "") + }.must_raise SlackAPI::SlackError + end + end + end +end diff --git a/specs/workspace_spec.rb b/specs/workspace_spec.rb new file mode 100644 index 00000000..32ef1abd --- /dev/null +++ b/specs/workspace_spec.rb @@ -0,0 +1,79 @@ +require_relative "test_helper" + +describe "select_channel" do + it "selects a channel as the current recipient when user inputs channel ID" do + channel_url = "channels.list" + channel = SlackAPI::Workspace.new() + + VCR.use_cassette("select_channel") do + response = channel.select_channel("CH2SKTKPC") + expect(response).must_equal "CH2SKTKPC" + end + end + it "selects a channel as the current recipient when user inputs channel name" do + channel = SlackAPI::Workspace.new() + VCR.use_cassette("select_channel") do + response = channel.select_channel("general") + expect(response).must_equal "general" + end + end + it "raises an error if the channel is not valid" do + channel = SlackAPI::Workspace.new() + VCR.use_cassette("select_channel") do + expect { channel.select_channel("fake channel") }.must_raise SlackAPI::SlackError + end + end +end + +describe "see_details" do + it "shows details for a selected channel" do + channel = SlackAPI::Workspace.new() + VCR.use_cassette("see_details_2") do + selected_channel = channel.select_channel("CH2SKTKPC") + channel_details = channel.see_channel_details("CH2SKTKPC") + + expect(channel_details).must_be_kind_of Array + expect(channel_details.length).must_equal 1 + expect(channel_details[0]).must_equal "name" => "general", "topic" => "Company-wide announcements", "member count" => 2, "id" => "CH2SKTKPC" + end + end +end + +# TESTS FOR USERS + +describe "select_user" do + it "selects a user as the current recipient when user inputs ID" do + user = SlackAPI::Workspace.new + VCR.use_cassette("select_user") do + response = user.select_user("UH3UT3SJK") + expect(response).must_equal "UH3UT3SJK" + end + end + it "selects a user as the current recipient when user inputs name" do + user = SlackAPI::Workspace.new + VCR.use_cassette("select_user") do + response = user.select_user("aribray") + expect(response).must_equal "UH3UT3SJK" + end + end + it "raises a SlackError if the user's name or id is invalid" do + user = SlackAPI::Workspace.new + VCR.use_cassette("select_user") do + expect { user.select_user("fakeuser") }.must_raise SlackAPI::SlackError + end + end +end + +describe "see_details" do + it "shows details for selected user" do + user = SlackAPI::Workspace.new + VCR.use_cassette("see_details_1") do + selected_user = user.select_user("UH3UT3SJK") + user_details = user.see_user_details(selected_user) + + expect(user_details).must_be_kind_of Array + expect(user_details.length).must_equal 1 + expect(user_details[0]).must_equal "name" => "aribray", "real name" => "Ariana Bray", "slack id" => "UH3UT3SJK" + end + end +end