diff --git a/lib/channel.rb b/lib/channel.rb new file mode 100644 index 00000000..30e3d674 --- /dev/null +++ b/lib/channel.rb @@ -0,0 +1,31 @@ +require "awesome_print" +require 'table_print' +require_relative "recipient" + +module Slack + class Channel < Recipient + BASE_URL = "https://slack.com/api/channels.list" + PARAMETERS = { token: ENV["SLACK_API_TOKEN"] } + + attr_reader :topic, :member_count + + def initialize(name, slack_id, topic, member_count) + super(name, slack_id) + @name = name + @topic = topic + @member_count = member_count + end + + def self.list + channel_data = self.get(BASE_URL, PARAMETERS) + + channel_data["channels"].map do |channel| + self.new(channel["name"], channel["id"], channel["topic"]["value"], channel["members"].length) + end + end + + def channel_details + super.push("topic", "member_count") + end + end +end diff --git a/lib/recipient.rb b/lib/recipient.rb new file mode 100644 index 00000000..e3d23c5d --- /dev/null +++ b/lib/recipient.rb @@ -0,0 +1,55 @@ +require "httparty" +require "awesome_print" +require 'table_print' +require "dotenv" +Dotenv.load + +module Slack + class ResponseError < StandardError; end + + class Recipient + BASE_URL = "https://slack.com/api/chat.postMessage" + + attr_reader :slack_id, :name + + def initialize(slack_id, name) + @slack_id = slack_id + @name = name + # raise error here if name isn't a string + end + + def self.get(base_url, parameters) + response = HTTParty.get(base_url, query: parameters) + unless response.code == 200 && response.parsed_response["ok"] + raise ResponseError, response["error"] + end + + return response + end + + def send_message(channel, text) + message_request = HTTParty.post(BASE_URL, + headers: { "Content-Type" => "application/x-www-form-urlencoded" }, + body: { + token: ENV["SLACK_API_TOKEN"], + channel: channel, + text: text, + # as_user: true, + }) + + if message_request["ok"] + return true + else + raise ResponseError, "There was an error sending your message" + end + end + + def self.list + raise NotImplementedError, "Implement me in a child class!" + end + + def details + ["name", "slack_id"] + end + end # class +end # module diff --git a/lib/slack.rb b/lib/slack.rb deleted file mode 100755 index 960cf2f7..00000000 --- a/lib/slack.rb +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env ruby - -def main - puts "Welcome to the Ada Slack CLI!" - - # TODO project - - puts "Thank you for using the Ada Slack CLI" -end - -main if __FILE__ == $PROGRAM_NAME \ No newline at end of file diff --git a/lib/slack_cli.rb b/lib/slack_cli.rb new file mode 100644 index 00000000..307d17b1 --- /dev/null +++ b/lib/slack_cli.rb @@ -0,0 +1,78 @@ +require "awesome_print" +require "table_print" +require_relative "workspace" + +Dotenv.load + +def main + puts "Welcome to the Ada Slack CLI!" + workspace = Slack::Workspace.new + # TODO project + + puts "This workspace has #{Slack::Channel.list.length} channels." + puts "This workspace has #{Slack::User.list.length} users." + + loop do + puts "\n\t\t~ MENU ~ + \t|1|::List Channels + \t|2|::List Users + \t|3|::Select User + \t|4|::Select Channel + \t|5|::Send Message + \t|6|::Quit" + puts "\nPlease select from the Menu:" + answer = gets.chomp.to_i + + # List Stuff + case answer + when 1 + # ap Slack::Channel.list => {:width => 12} + tp workspace.channels, "name", "slack_id", "topic", "member_count" + when 2 + # ap Slack::User.list => { :width => 12 } + tp workspace.users, "slack_id", :Name => { :display_method => "real_name" }, + :include => { :User_Name => { :display_method => "name" } } + when 3 + puts "Please enter a SlackID or full name:" + name_or_id = gets.chomp + + workspace.select_user(name_or_id) + # selection = workspace.select_user(name_or_id) + + puts "Show additional details for #{name_or_id}? (Y/N)" + choice = gets.chomp.downcase + + if choice == "y" + # puts "#{workspace.show_details}" + tp workspace.show_details, "slack_id", :Name => { :display_method => "real_name" }, + :include => { :User_Name => { :display_method => "name" } } + # call show_details method and puts ap it + end + when 4 + puts "Please enter a channel name or channel id:" + name_or_id = gets.chomp + + workspace.select_channel(name_or_id) + + puts "Show additional details for #{name_or_id}? (Y/N)" + choice = gets.chomp.downcase + + if choice == "y" + # puts "#{workspace.show_details}" + tp workspace.show_details, "name", "slack_id", "topic", "member_count" + end + when 5 + puts "What would you like your message to say ?" + message = gets.chomp + workspace.send_message(message) + puts "Your message has been sent! Yay!" + when 6 + break + else + puts "Please select from Menu Items." + end + end + puts "Thank you for using the Ada Slack CLI" +end + +main if __FILE__ == $PROGRAM_NAME diff --git a/lib/user.rb b/lib/user.rb new file mode 100644 index 00000000..c28cc351 --- /dev/null +++ b/lib/user.rb @@ -0,0 +1,28 @@ +require "awesome_print" +require 'table_print' +require_relative "recipient" + +module Slack + class User < Recipient + BASE_URL = "https://slack.com/api/users.list" + PARAMETER = { token: ENV["SLACK_API_TOKEN"] } + + attr_reader :real_name, :status_text + + def initialize(name, slack_id, real_name) + super(name, slack_id) + @real_name = real_name + end + + def self.list + user_data = self.get(BASE_URL, PARAMETER) + user_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 diff --git a/lib/workspace.rb b/lib/workspace.rb new file mode 100755 index 00000000..6c4b1c2c --- /dev/null +++ b/lib/workspace.rb @@ -0,0 +1,70 @@ +require "dotenv" +require "httparty" +require "table_print" +require "awesome_print" +require_relative "user" +require_relative "channel" + +Dotenv.load + +module Slack + class ResponseError < StandardError; end + + class Workspace + BASE_URL = "https://slack.com/api/users.list" + attr_reader :users, :channels + attr_accessor :selection + + def initialize + @users = User.list + @channels = Channel.list + @selection = nil + end + + def select_user(name_or_id) + users.each do |user| + if name_or_id == user.name || name_or_id == user.slack_id || name_or_id == user.real_name + @selection = user + end + end + if @selection == nil + return "Sorry, #{name_or_id} is not a valid user." + end + return @selection + end + + def select_channel(name_or_id) + @channels.each do |channel| + if name_or_id == channel.name || name_or_id == channel.slack_id + @selection = channel + end + end + + if @selection == nil + return "Sorry, #{name_or_id} is not a valid channel." + end + return @selection + end + + def show_details + return @selection, @selection.details + # if @selection == nil + # return false + # ap @selection, @selection.details + # end + tp @selection, @selection.details + end + + def send_message(text) + if @selection == nil + return false + end + + if text == "" + return nil + end + + return @selection.send_message(@selection.slack_id, text) + end + end +end diff --git a/specs/channel_spec.rb b/specs/channel_spec.rb new file mode 100644 index 00000000..9a8c529e --- /dev/null +++ b/specs/channel_spec.rb @@ -0,0 +1,51 @@ +require_relative "test_helper" + +describe "Channels" do + describe "self get method" do + it "returns a response from api for channels list" do + VCR.use_cassette("connect to channel api") do + url = "http://slack.com/api/channels.list" + query = { token: ENV["SLACK_API_TOKEN"] } + request = Slack::Channel.get(url, query) + + expect(request["ok"]).must_equal(true) + end + end + end + + it "raises exception if get request fails" do + VCR.use_cassette("connect to channel api") do + url = "https://slack.com/api/channel.list" + query = { token: "idontworkidontworkkkkkk" } + + expect { + Slack::Channel.get(url, query) + }.must_raise Slack::ResponseError + end + end + + describe "self list method" do + it "returns channels array" do + VCR.use_cassette("connect to channel api") 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 "channel details method" do + it "returns an array that contains correct strings" do + channel = Slack::Channel.new("i", "play", "electric", "bass") + 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 +end diff --git a/specs/recipient_spec.rb b/specs/recipient_spec.rb new file mode 100644 index 00000000..4796b0b5 --- /dev/null +++ b/specs/recipient_spec.rb @@ -0,0 +1,14 @@ +require_relative "test_helper" + +describe "Recipient Class" do + describe "self list method" do + it "raises an error if not implemented in a subclass" do + expect { Slack::Recipient.list }.must_raise NotImplementedError + end + end + + describe "send message method" do + it "raises error if parameters are incorrect" do + end + end +end diff --git a/specs/test_helper.rb b/specs/test_helper.rb index 81ccd06b..229abe72 100644 --- a/specs/test_helper.rb +++ b/specs/test_helper.rb @@ -1,15 +1,29 @@ -require 'simplecov' +require "simplecov" SimpleCov.start -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 "vcr" + +require_relative "../lib/user" +require_relative "../lib/channel" +require_relative "../lib/workspace" +require_relative "../lib/recipient" +require_relative "../lib/slack_cli" 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.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["SLACK_API_TOKEN"] + end +end diff --git a/specs/user_spec.rb b/specs/user_spec.rb new file mode 100644 index 00000000..f8acb7a0 --- /dev/null +++ b/specs/user_spec.rb @@ -0,0 +1,55 @@ +require_relative "test_helper" + +describe "User Class" do + describe "self get method" do + it "successfully connects to API" do + VCR.use_cassette("connect to user api") do + url = "https://slack.com/api/users.list" + query = { token: ENV["SLACK_API_TOKEN"] } + request = Slack::User.get(url, query) + + expect(request["ok"]).must_equal(true) + end + end + end + + it "raises and exception if API call fails" do + VCR.use_cassette("api fail") do + url = "https://slack.com/api/users.list" + query = { token: "i love cats" } + + expect { Slack::User.get(url, query) }.must_raise(Slack::ResponseError) + end + end + + describe "self list method" do + it "returns array with user instances" do + VCR.use_cassette("connect to user api") do + user = Slack::User.list + + expect(user).must_be_kind_of(Array) + # check at index that its an instance of user + end + end + + it "correctly loads user information" do + VCR.use_cassette("connect to user api") do + users = Slack::User.list + expect(users[1].name).must_equal "faiza.ahsan1222" + expect(users[1].real_name).must_equal "Faiza Husain" + expect(users[1].slack_id).must_equal "UH2NWFHTM" + expect(users.length).must_equal 3 + end + end + + describe "user details methods" do + it "returns an array with correct string values" do + user = Slack::User.new("I", "play", "bass") + expect(user.details).must_be_kind_of Array + expect(user.details[2]).must_equal "real_name" + expect(user.details[1]).must_equal "slack_id" + expect(user.details[0]).must_equal "name" + end + end + end +end diff --git a/specs/workspace_spec.rb b/specs/workspace_spec.rb new file mode 100644 index 00000000..393cec50 --- /dev/null +++ b/specs/workspace_spec.rb @@ -0,0 +1,141 @@ +require_relative "test_helper" + +describe "Workspace Class" do + describe "initialize method" do + it "lists users and channels" do + VCR.use_cassette("workspace information") do + workspace = Slack::Workspace.new + expect(workspace.users).must_be_kind_of(Array) + expect(workspace.channels).must_be_kind_of(Array) + (0..1).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 method" do + it "stores user inputted username in selection variable" do + VCR.use_cassette("workspace information") do + user_names = ["smarcha04", "faiza.ahsan1222", "slackbot"] + real_names = ["Stephanie Marchante", "Faiza Husain", "Slackbot"] + workspace = Slack::Workspace.new + + user_names.each_with_index do |user_name, i| + find_user = workspace.select_user(user_name) + selected_user = workspace.selection + expect(selected_user).must_be_kind_of Slack::User + expect(selected_user.real_name).must_equal "#{real_names[i]}" + end + end + end + + it "stores user inputted slackid in selection variable" do + VCR.use_cassette("workspace information") do + all_slack_ids = ["UH2NWFHTM", "UH2NX89A7", "USLACKBOT"] + all_real_names = ["Faiza Husain", "Stephanie Marchante", "Slackbot"] + + workspace = Slack::Workspace.new + + all_slack_ids.each_with_index do |slackid, i| + user_search = workspace.select_user(slackid) + select_user = workspace.selection + expect(select_user).must_be_kind_of(Slack::User) + expect(select_user.real_name).must_equal "#{all_real_names[i]}" + end + end + end + + it "returns error message if user input slackid or user name are invalid" do + VCR.use_cassette("workspace information") do + workspace = Slack::Workspace.new + user_search = workspace.select_user("steph steph") + selected_user = workspace.selection + assert_nil(selected_user, msg = nil) + end + end + end + + describe "select channel method" do + it "finds a channel by name and stores it in the selected variable" do + VCR.use_cassette("workspace information") do + channel_names = ["general", "random"] + topics = ["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| + workspace.select_channel(channel_name) + expect(workspace.selection).must_be_kind_of Slack::Channel + expect(workspace.selection.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") do + # slack_ids = ["CH2RA1JMS", "CH36MD2ER"] + # topics = ["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| + # expect(workspace.selection).must_be_kind_of(String) + # expect(workspace.select_channel(slack_id)).must_equal "#{topics[i]}" + # end + # end + # end + end + + it "gives an error message if user name or slack id ar invalid" do + VCR.use_cassette("workspace information") do + workspace = Slack::Workspace.new + search_channel = workspace.select_channel("crazy cat lady") + selected_channel = workspace.selection + assert_nil(selected_channel, msg = nil) + end + end + + describe "Show details method" do + it "returns details" do + end + it "returns false boolean if invalid user or channel is passed in" do + VCR.use_cassette("workspace information") do + workspace = Slack::Workspace.new + puts "BBBBBBBBBBBB" + puts "#{workspace}" + chosen_user = workspace.select_user("FaiFai") + expect(chosen_user).must_be_kind_of(String) + + chosen_user2 = workspace.select_channel("Thomas") + expect(chosen_user2).must_be_kind_of(String) + end + end + end + + describe "send message method" do + it "sends a message if all requirements are met" do + VCR.use_cassette("recipient send message") do + workspace = Slack::Workspace.new + workspace.select_user("smarcha04") + message = workspace.send_message("Man I love playing guitar.") + expect(message).must_equal(true) + end + end + + it "returns false if no channel or user are selected" do + VCR.use_cassette("recipient send message") do + workspace = Slack::Workspace.new + message = workspace.send_message("Man I love playing guitar.") + expect(message).must_equal false + end + end + + it "returns nil if incorrect message is inputted" do + VCR.use_cassette("recipient send message") do + workspace = Slack::Workspace.new + message = workspace.send_message("") + expect(message).must_equal false + end + end + end +end