diff --git a/lib/channels.rb b/lib/channels.rb new file mode 100644 index 00000000..d6b8f46b --- /dev/null +++ b/lib/channels.rb @@ -0,0 +1,32 @@ +require_relative "recipient" + +module Slack + class Channel < Recipient + URL = "https://slack.com/api/channels.list" + PARAM = {token: ENV["KEY"]} + + attr_reader :topic, :member_count + + def initialize(slack_id, name, topic, member_count) + super(slack_id, name) + @name = name + @topic = topic + @member_count = member_count + end + + def self.list + json_data = self.get(URL, PARAM) + + json_data["channels"].map do |channel| + self.new(channel["id"], channel["name"], channel["topic"]["value"], channel["members"].length) + end + end + + def details + super.push("topic", "member_count") + end + end +end + +# ap Slack::User.get("https://slack.com/api/users.list", {token: ENV["KEY"]}) +# # puts Slack::User.list(potato) diff --git a/lib/recipient.rb b/lib/recipient.rb new file mode 100644 index 00000000..8000a418 --- /dev/null +++ b/lib/recipient.rb @@ -0,0 +1,59 @@ +require "httparty" +require "dotenv" + +Dotenv.load + +module Slack + class ResponseError < StandardError; end + + class Recipient + URL = "https://slack.com/api/chat.postMessage" + + attr_reader :slack_id, :name + + def initialize(slack_id, name) + @slack_id = slack_id + @name = name + end + + def self.get(url, params) + user_data = HTTParty.get(url, query: params) + + if user_data["ok"] == false + raise ResponseError, "There was an error!\nMessage: #{user_data["error"]}" + end + + return user_data + end + + def send_message(message, selected) + message_request = HTTParty.post(URL, + body: { + token: ENV["KEY"], + text: message, + channel: selected, + as_user: true, + }, + headers: {"Content-Type" => "application/x-www-form-urlencoded"}) + + if message_request["ok"] == false + raise ResponseError, "There was an error!\nMessage: #{message_request["error"]}" + end + + return message_request + end + + def details + ["name", "slack_id"] + end + + def self.list + raise NotImplementedError, "Implement me in a child class!" + end + end +end + +# slack = Recipient.new +# slack.get("https://slack.com/api/channels.list", {token: ENV["KEY"]}) + +# puts slack diff --git a/lib/slack.rb b/lib/slack.rb index 960cf2f7..b95d3e81 100755 --- a/lib/slack.rb +++ b/lib/slack.rb @@ -1,11 +1,69 @@ #!/usr/bin/env ruby +require_relative "workspace" +require "table_print" +require "colorize" +Dotenv.load + +# module Slack def main - puts "Welcome to the Ada Slack CLI!" + # users = Slack::User + # channel = Slack::Channel + workspace = Slack::Workspace.new + + puts "Welcome to the Ada Slack CLI!".colorize(:magenta) + print "#{workspace.users.length} users and #{workspace.channels.length} ".colorize(:magenta) + puts "channels were uploaded.".colorize(:magenta) - # TODO project + selection = 1 + while selection != 6 + puts "\nPlease make a selection:\n".colorize(:magenta) + puts "1. list users".colorize(:blue) + puts "2. list channels".colorize(:green) + puts "3. select user".colorize(:blue) + puts "4. select channel".colorize(:green) + puts "5. details".colorize(:yellow) + puts "6. send message".colorize(:yellow) + puts "7. quit\n".colorize(:light_red) - puts "Thank you for using the Ada Slack CLI" + selection = gets.chomp + + case selection + when "1", "list users" + tp workspace.users, "slack_id", :Name => {:display_method => "real_name"}, + :include => {:User_Name => {:display_method => "name"}} + when "2", "list channels" + tp workspace.channels, "name", "slack_id", "topic", "member_count" + when "3", "select user" + print "Please enter in the user's USER_NAME or SLACK_ID: ".colorize(:blue) + user_descriptor = gets.chomp + puts "\n#{workspace.select_user(user_descriptor)}".colorize(:light_red) + when "4", "select channel" + print "Please enter in the channel's NAME or SLACK_ID: ".colorize(:green) + channel_descriptor = gets.chomp + puts "\n#{workspace.select_channel(channel_descriptor)}".colorize(:light_red) + when "5", "details" + if workspace.show_details == false + puts "No channel or user has been selected.".colorize(:light_red) + else + workspace.show_details + end + when "6", "send message" + print "Please enter in a message to send: ".colorize(:yellow) + message = gets.chomp + sending_message = workspace.send_message(message) + if sending_message == false + puts "--- No channel or user selected. ----".colorize(:light_red) + elsif sending_message == nil + puts "--- Invalid message, unable to send. ---".colorize(:light_red) + else puts "--- Message sent succesfully! ---".colorize(:blue) end + when "7", "quit" + puts "Thank you for using the Ada Slack CLI".colorize(:magenta) + exit + end # end + end end -main if __FILE__ == $PROGRAM_NAME \ No newline at end of file +# end + +main if __FILE__ == $PROGRAM_NAME diff --git a/lib/user.rb b/lib/user.rb new file mode 100644 index 00000000..49b2b271 --- /dev/null +++ b/lib/user.rb @@ -0,0 +1,30 @@ +require_relative "recipient" + +module Slack + class User < Recipient + URL = "https://slack.com/api/users.list" + PARAM = {token: ENV["KEY"]} + + attr_reader :real_name + + def initialize(slack_id, name, real_name) + super(slack_id, name) + @real_name = real_name + end + + def self.list + json_data = self.get(URL, PARAM) + + json_data["members"].map do |user| + self.new(user["id"], user["name"], user["profile"]["real_name"]) + end + end + + def details + super << "real_name" + end + end +end + +# ap Slack::User.get("https://slack.com/api/users.list", {token: ENV["KEY"]}) +# # puts Slack::User.list(potato) diff --git a/lib/workspace.rb b/lib/workspace.rb new file mode 100644 index 00000000..5b5a2650 --- /dev/null +++ b/lib/workspace.rb @@ -0,0 +1,58 @@ +# workspace file for keeping all things slack +require "dotenv" +require "httparty" + +require_relative "user" +require_relative "channels" + +Dotenv.load + +module Slack + class Workspace + URL = "https://slack.com/api/users.list" + attr_reader :users, :channels + attr_accessor :selected + + def initialize + @users = User.list + @channels = Channel.list + @selected = nil + end + + def select_user(user_descriptor) + users.find do |user| + if user_descriptor == user.name || user_descriptor == user.slack_id + @selected = user + end + end + + if @selected == nil + return "Could not find a user with USER_NAME or SLACK_ID #{user_descriptor}." + end + end + + def select_channel(channel_descriptor) + channels.find do |channel| + if channel_descriptor == channel.name || channel_descriptor == channel.slack_id + @selected = channel + end + end + + if @selected == nil + return "Could not find a channel with NAME or SLACK_ID #{channel_descriptor}." + end + end + + def show_details #currently_selected_recipient + return false if @selected == nil + tp @selected, @selected.details + end + + def send_message(message) + return false if @selected == nil + return nil if message == "" + + return @selected.send_message(message, @selected.slack_id) + end + end +end diff --git a/specs/channels_spec.rb b/specs/channels_spec.rb new file mode 100644 index 00000000..b4d83199 --- /dev/null +++ b/specs/channels_spec.rb @@ -0,0 +1,52 @@ +require_relative "test_helper" + +describe "Channels" do + describe "self.get" do + it "will successfully get a response from Slack API for user list" do + VCR.use_cassette("channel_information_find") do + url = "http://slack.com/api/channels.list" + query = {token: ENV["KEY"]} + request = Slack::Channel.get(url, query) + + expect(request["ok"]).must_equal true + end + end + + it "will raise an exception if the GET request fails" do + VCR.use_cassette("channel_information_find") do + url = "https://slack.com/api/channel.list" + query = {token: "dkdkdkdkdkdkd"} + + expect { + Slack::Channel.get(url, query) + }.must_raise Slack::ResponseError + end + end + end +end + +describe "Self.list" do + it "return an array of channels" do + VCR.use_cassette("channel_information_find") do + channels = Slack::Channel.list + + expect(channels).must_be_kind_of Array + + (0..channels.length - 1).each do |i| + expect(channels[i]).must_be_kind_of Slack::Channel + end + end + + describe "#details" do + it "must return an array that contains the correct strings" do + channel = Slack::Channel.new("potato", "head", "toy", "story") + expect(channel.details).must_be_kind_of Array + expect(channel.details[0]).must_equal "name" + expect(channel.details[1]).must_equal "slack_id" + expect(channel.details[2]).must_equal "topic" + expect(channel.details[3]).must_equal "member_count" + end + end + # # end end + end +end diff --git a/specs/recipient_spec.rb b/specs/recipient_spec.rb new file mode 100644 index 00000000..1d94ca52 --- /dev/null +++ b/specs/recipient_spec.rb @@ -0,0 +1,16 @@ +require_relative "test_helper" + +describe "Recipient Class" do + describe "self.list" do + it "raises an Error if invoked directly (without subclassing)" do + expect { + Slack::Recipient.list + }.must_raise NotImplementedError + end + end + + describe "#send_message" do + it "raises an Error if incorrect parameters are given" do + end + end +end diff --git a/specs/slack_spec.rb b/specs/slack_spec.rb new file mode 100644 index 00000000..e69de29b diff --git a/specs/test_helper.rb b/specs/test_helper.rb index 81ccd06b..87093470 100644 --- a/specs/test_helper.rb +++ b/specs/test_helper.rb @@ -1,15 +1,35 @@ -require 'simplecov' -SimpleCov.start +require "simplecov" +SimpleCov.start do + add_filter %r{^/spec/} +end -require 'minitest' -require 'minitest/autorun' -require 'minitest/reporters' -require 'minitest/skip_dsl' -require 'vcr' +require "minitest" +require "minitest/autorun" +require "minitest/reporters" +require "minitest/skip_dsl" +require "webmock/minitest" +require "vcr" +require "dotenv" +require "table_print" +Dotenv.load Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new +require_relative "../lib/recipient" +require_relative "../lib/user" +require_relative "../lib/slack" +require_relative "../lib/channels" +require_relative "../lib/workspace" + VCR.configure do |config| - config.cassette_library_dir = "specs/cassettes" - config.hook_into :webmock -end \ No newline at end of file + config.cassette_library_dir = "specs/cassettes" # folder where casettes will be located + config.hook_into :webmock # tie into this other tool called webmock + 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["KEY"] + end +end diff --git a/specs/user_spec.rb b/specs/user_spec.rb new file mode 100644 index 00000000..b70c52a2 --- /dev/null +++ b/specs/user_spec.rb @@ -0,0 +1,60 @@ +require_relative "test_helper" + +describe "User Class" do + describe "self.get" do + it "sucessfully gets a response from Slack API for user list" do + VCR.use_cassette("user_information_find") do + url = "https://slack.com/api/users.list" + query = {token: ENV["KEY"]} + request = Slack::User.get(url, query) + + expect(request["ok"]).must_equal true + end + end + + it "will raise an exception if the GET request fails" do + VCR.use_cassette("user_information_find") do + url = "https://slack.com/api/users.list" + query = {token: "dkdkdkdkdkdkd"} + + expect { + Slack::User.get(url, query) + }.must_raise Slack::ResponseError + end + end + end + + describe "self.list" do + it "returns an array that contains instances of users" do + VCR.use_cassette("user_information_find") do + users = Slack::User.list + + expect(users).must_be_kind_of Array + (0..users.length - 1).each do |i| + expect(users[i]).must_be_kind_of Slack::User + end + end + end + + it "loads all user information correctly" do + VCR.use_cassette("user_information_find") do + users = Slack::User.list + expect(users[1].name).must_equal "kimberly.fasbender" + expect(users[1].real_name).must_equal "Kim Fasbender" + expect(users[1].slack_id).must_equal "UH408BVL7" + expect(users.length).must_equal 3 + end + end + + describe "#details" do + it "must return an array that contains the correct strings" do + user = Slack::User.new("potato", "head", "toy") + expect(user.details).must_be_kind_of Array + expect(user.details[0]).must_equal "name" + expect(user.details[1]).must_equal "slack_id" + expect(user.details[2]).must_equal "real_name" + end + end + # # end end + end +end diff --git a/specs/workspace_spec.rb b/specs/workspace_spec.rb new file mode 100644 index 00000000..b5f0af63 --- /dev/null +++ b/specs/workspace_spec.rb @@ -0,0 +1,156 @@ +require_relative "test_helper" + +describe "Workspace Class" do + describe "#initialize" do + it "has a list of users & a list of channels" do + VCR.use_cassette("workspace_information_find") do + workspace = Slack::Workspace.new + expect(workspace.users).must_be_kind_of Array + expect(workspace.channels).must_be_kind_of Array + (0..2).each do |i| + expect(workspace.users[i]).must_be_kind_of Slack::User + expect(workspace.channels[i]).must_be_kind_of Slack::Channel + end + end + end + end + + describe "#select_user" do + it "finds a user by username and stores it in the selected variable" do + VCR.use_cassette("workspace_information_find") do + user_names = ["kimberly.fasbender", "scarlettsteph07", "cloudylopez"] + real_names = ["Kim Fasbender", "Scarlett", "Cloudy Lopez"] + workspace = Slack::Workspace.new + + user_names.each_with_index do |user_name, i| + find_user = workspace.select_user(user_name) + selected_user = workspace.selected + expect(selected_user).must_be_kind_of Slack::User + expect(selected_user.real_name).must_equal "#{real_names[i]}" + end + end + end + + it "finds a user by slack id and stores it in the selected variable" do + VCR.use_cassette("workspace_information_find") do + slack_ids = ["UH408BVL7", "UH5EEFU0N", "UH599D6J0"] + real_names = ["Kim Fasbender", "Cloudy Lopez", "Scarlett"] + workspace = Slack::Workspace.new + + slack_ids.each_with_index do |slack_id, i| + find_user = workspace.select_user(slack_id) + selected_user = workspace.selected + expect(selected_user).must_be_kind_of Slack::User + expect(selected_user.real_name).must_equal "#{real_names[i]}" + end + end + end + + it "returns an error message if user_name or slack_id are invalid" do + VCR.use_cassette("workspace_information_find") do + workspace = Slack::Workspace.new + find_user = workspace.select_user("potato daniels") + selected_user = workspace.selected + assert_nil(selected_user, msg = nil) + end + end + end + + describe "#select_channel" do + it "finds a channel by name and stores it in the selected variable" do + VCR.use_cassette("workspace_information_find") do + channel_names = ["puppers", "general", "random"] + topics = ["All doggos all the time! :dog:", + "Company-wide announcements and work-based matters", + "Non-work banter and water cooler conversation"] + workspace = Slack::Workspace.new + + channel_names.each_with_index do |channel_name, i| + find_channel = workspace.select_channel(channel_name) + selected_channel = workspace.selected + expect(selected_channel).must_be_kind_of Slack::Channel + expect(selected_channel.topic).must_equal "#{topics[i]}" + end + end + end + + it "finds a channel by slack id and stores it in the selected variable" do + VCR.use_cassette("workspace_information_find") do + slack_ids = ["CH317B6EN", "CH408C1CP", "CH4AZQMJS"] + topics = ["All doggos all the time! :dog:", + "Company-wide announcements and work-based matters", + "Non-work banter and water cooler conversation"] + workspace = Slack::Workspace.new + + slack_ids.each_with_index do |slack_id, i| + find_channel = workspace.select_channel(slack_id) + selected_channel = workspace.selected + expect(selected_channel).must_be_kind_of Slack::Channel + expect(selected_channel.topic).must_equal "#{topics[i]}" + end + end + end + + it "returns an error message if user_name or slack_id are invalid" do + VCR.use_cassette("workspace_information_find") do + workspace = Slack::Workspace.new + find_channel = workspace.select_channel("potato daniels") + selected_channel = workspace.selected + assert_nil(selected_channel, msg = nil) + end + end + + describe "#show_details" do + it "returns an instance of table_print when a valid paramter is passed" do + VCR.use_cassette("workspace_information_find") do + workspace = Slack::Workspace.new + select_user = workspace.select_user("kimberly.fasbender") + expect(workspace.show_details).must_be_kind_of TablePrint::Returnable + + select_channel = workspace.select_channel("puppers") + expect(workspace.show_details).must_be_kind_of TablePrint::Returnable + end + end + + it "returns false if an invalid channel/user is passed to it" do + VCR.use_cassette("workspace_information_find") do + workspace = Slack::Workspace.new + select_user = workspace.select_user("Reginald") + expect(workspace.show_details).must_equal false + + select_channel = workspace.select_channel("Thomas") + expect(workspace.show_details).must_equal false + end + end + end + end + + describe "#send_message" do + it "sends a message if all requirements are met" do + VCR.use_cassette("recipient_information_find") do + workspace = Slack::Workspace.new + workspace.select_user("cloudylopez") + message = workspace.send_message("You're the best!! :dog:") + expect(message["ok"]).must_equal true + end + end + + it "returns false if no channel or user are selected" do + VCR.use_cassette("recipient_information_find") do + workspace = Slack::Workspace.new + message = workspace.send_message("You're the best!! :dog:") + expect(message).must_equal false + end + end + + it "returns nil if invalid message is entered" do + VCR.use_cassette("recipient_information_find") do + workspace = Slack::Workspace.new + message = workspace.send_message("") + expect(message).must_equal false + end + end + end + + # end end +end