diff --git a/.gitignore b/.gitignore index 8d6a243f..451dd5dc 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ build-iPhoneSimulator/ # Ignore environemnt variables .env +.DS_Store # Ignore cassette files /specs/cassettes/ diff --git a/lib/channel.rb b/lib/channel.rb new file mode 100644 index 00000000..8bb8988d --- /dev/null +++ b/lib/channel.rb @@ -0,0 +1,37 @@ +require "dotenv" +Dotenv.load +require "httparty" + +class Channel + attr_reader :channel_name, :id, :topic, :members, :member_count + BASE_URL = "https://slack.com/api/channels.list" + TOKEN = ENV["SLACK_API_TOKEN"] + + def initialize(channel_name, id, topic, members) + @channel_name = channel_name + @id = id + @topic = topic + @members = members + @member_count = members.length + end + + def self.get + query = { + token: TOKEN, + } + channel_info = HTTParty.get(BASE_URL, query: query) + if channel_info["ok"] == false + raise ArgumentError, "The error code is #{channel_info.code} and the reason is: #{channel_info.message}" + end + return channel_info + end + + def self.list + channel_info = Channel.get + channel_list = channel_info["channels"] + channels = channel_list.map do |channel| + Channel.new(channel["name"], channel["id"], channel["topic"]["value"], channel["members"]) + end + return channels + end +end diff --git a/lib/slack.rb b/lib/slack.rb index 960cf2f7..8b9af819 100755 --- a/lib/slack.rb +++ b/lib/slack.rb @@ -1,11 +1,67 @@ -#!/usr/bin/env ruby +require "dotenv" +Dotenv.load +require "table_print" +require "httparty" +require "colorize" +require_relative "workspace" +require_relative "user" +require_relative "channel" def main - puts "Welcome to the Ada Slack CLI!" + work_space = Workspace.new + puts "Welcome to the Ada Slack CLI!".colorize(:color => :blue, :mode => :bold) + puts "\nPlease Choose from the following options:\n1. List Users\n2. List Channels\n3. Select User\n4. Select Channel\n5. Details\n6. Send Message\n7. Quit".colorize(:color => :blue, :mode => :bold) + choice = gets.chomp.upcase - # TODO project - - puts "Thank you for using the Ada Slack CLI" + until choice == "QUIT" + if choice == "LIST USERS" + puts "\n" + tp work_space.users, "username", "real_name", "id" + elsif choice == "LIST CHANNELS" + puts "\n" + tp work_space.channels, "channel_name", "id", "topic" + elsif choice == "SELECT USER" + puts "Here is a list of users:".colorize(:color => :magenta) + tp work_space.users, "username", "id" + begin + puts "Please enter a username or Slack ID:".colorize(:color => :blue, :mode => :bold) + user_input = gets.chomp + user_recipient = work_space.select_user(user_input) + rescue ArgumentError + puts "The username or SlackID is invalid." + end + elsif choice == "SELECT CHANNEL" + puts "Here is a list of channels:".colorize(:color => :magenta) + tp work_space.channels, "channel_name", "id", "topic", "members" + begin + puts "Please enter channel name or Slack ID:".colorize(:color => :blue, :mode => :bold) + channel_input = gets.chomp + channel_recipient = work_space.select_channel(channel_input) + rescue ArgumentError + puts "The channel name or SlackID is invalid." + end + elsif choice == "DETAILS" + begin + tp work_space.show_details + rescue ArgumentError + puts "There is no recipient selected. Please select a user or a channel." + end + elsif choice == "SEND MESSAGE" + puts "Please enter your message below:" + user_message = gets.chomp + begin + work_space.send_message(user_message) + rescue ArgumentError + puts "The message is invalid. Please try again." + rescue NoMethodError + puts "Message failed to send. Please select a recipient and try again." + end + puts "Your message was successfully sent to the recipient!" + end + puts "\nWhat would you like to do next?\n1. List Users\n2. List Channels\n3. Select User\n4. Select Channel\n5. Details\n6. Send Message\n7. Quit".colorize(:color => :blue, :mode => :bold) + choice = gets.chomp.upcase + end + puts "Thank you for using the Ada Slack CLI!".colorize(:color => :green, :mode => :bold) 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..70fa2971 --- /dev/null +++ b/lib/user.rb @@ -0,0 +1,36 @@ +require "dotenv" +Dotenv.load +require "httparty" + +class User + attr_reader :username, :real_name, :id + BASE_URL = "https://slack.com/api/users.list" + TOKEN = ENV["SLACK_API_TOKEN"] + + def initialize(real_name, username, id) + @username = username + @real_name = real_name + @id = id + @user_info = User.get + end + + def self.get + query = { + token: TOKEN, + } + @user_info = HTTParty.get(BASE_URL, query: query) + if @user_info["ok"] == false + raise ArgumentError, "The error code is #{@user_info.code} and the reason is: #{@user_info["error"]}" + end + return @user_info + end + + def self.list + user_info = User.get + user_list = user_info["members"] + users = user_list.map do |user| + User.new(user["real_name"], user["name"], user["id"]) + end + return users + end +end diff --git a/lib/verification.rb b/lib/verification.rb new file mode 100644 index 00000000..3061338a --- /dev/null +++ b/lib/verification.rb @@ -0,0 +1,15 @@ +require "dotenv" +require "httparty" +Dotenv.load +require "ap" + +BASE_URL = "https://slack.com/api/channels.list" +query = { + token: ENV["SLACK_API_TOKEN"], +} +channel_info = HTTParty.get(BASE_URL, query: query) +channel_list = channel_info["channels"] +channel_names = channel_list.map do |channel| + channel["name"] +end +ap channel_names diff --git a/lib/workspace.rb b/lib/workspace.rb new file mode 100644 index 00000000..575951f6 --- /dev/null +++ b/lib/workspace.rb @@ -0,0 +1,76 @@ +require_relative "user" +require_relative "channel" +require_relative "slack" +require "dotenv" +require "httparty" +require "table_print" +tp.set User, :username, :id +tp.set Channel, :channel_name, :id, :members, :topic +Dotenv.load + +class Workspace + attr_reader :selected, :users, :channels + + def initialize + @users = User.list + @channels = Channel.list + @selected = nil + end + + def select_user(user_identifier) + selected_user = nil + @users.each do |user| + if user.username == user_identifier || user.id == user_identifier + selected_user = user + end + end + if selected_user == nil + raise ArgumentError, "That user is invalid" + else + @selected = selected_user + return @selected + end + end + + def select_channel(channel_identifier) + selected_channel = nil + @channels.each do |channel| + if channel.channel_name == channel_identifier || channel.id == channel_identifier + selected_channel = channel + end + end + if selected_channel == nil + raise ArgumentError, "That channel is invalid" + else + @selected = selected_channel + return @selected + end + end + + def show_details + if @selected == nil + raise ArgumentError + else + return @selected + end + end + + def send_message(message) + post_url = "https://slack.com/api/" + token = ENV["SLACK_API_TOKEN"] + response = HTTParty.post( + "#{post_url}/chat.postMessage", + body: { + token: token, + text: message, + channel: @selected.id, + }, + headers: {"Content-Type" => "application/x-www-form-urlencoded"}, + ) + if response["ok"] + return response["ok"] + else + raise ArgumentError + end + end +end diff --git a/specs/channel_spec.rb b/specs/channel_spec.rb new file mode 100644 index 00000000..26274b33 --- /dev/null +++ b/specs/channel_spec.rb @@ -0,0 +1,39 @@ +require_relative "test_helper" +require "pry" + +describe "Channel class" do + describe "Channel#initialize" do + it "initializes a Channel object" do + VCR.use_cassette("Channel") do + response = Channel.new("fur_babes", "1234", "pets", ["AUAIWFS"]) + expect(response).must_be_instance_of Channel + end + end + end + + describe "Channel#get" do + it "returns information from the API" do + VCR.use_cassette("Channel") do + response = Channel.get + expect(response["ok"]).must_equal true + end + end + end + + describe "Channel#list" do + it "includes a known channel" do + VCR.use_cassette("Channel") do + response = Channel.list + expect(response[0]).must_be_instance_of Channel + expect(response[0].member_count).must_be_instance_of Integer + end + end + + it "returns correct number of channels" do + VCR.use_cassette("Channel") do + response = Channel.list.length + expect(response).must_equal 3 + end + end + end +end diff --git a/specs/test_helper.rb b/specs/test_helper.rb index 81ccd06b..efe23561 100644 --- a/specs/test_helper.rb +++ b/specs/test_helper.rb @@ -1,15 +1,31 @@ -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 "webmock/minitest" +require "httparty" +require "dotenv" +Dotenv.load + +require_relative "../lib/slack.rb" +require_relative "../lib/channel.rb" +require_relative "../lib/user.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, + :match_requests_on => [:method, :uri, :body], + } + 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..b55f3a63 --- /dev/null +++ b/specs/user_spec.rb @@ -0,0 +1,44 @@ +require_relative "test_helper" + +describe "User class" do + describe "User#initialize" do + it "initializes a User object" do + VCR.use_cassette("User") do + response = User.new("Larry", "Truck", "1234") + expect(response).must_be_instance_of User + end + end + end + + describe "User#get" do + it "returns information from the API" do + VCR.use_cassette("User") do + response = User.get + expect(response["ok"]).must_equal true + end + end + end + + describe "User#list" do + it "includes a known User" do + VCR.use_cassette("User") do + response = User.list + expect(response[0]).must_be_instance_of User + end + end + + it "User details are correct" do + VCR.use_cassette("User") do + response = User.list + expect(response[1].username).must_equal "amyesh08" + end + end + + it "returns correct number of Users" do + VCR.use_cassette("User") do + response = User.list.length + expect(response).must_equal 3 + end + end + end +end diff --git a/specs/workspace_spec.rb b/specs/workspace_spec.rb new file mode 100644 index 00000000..937cbf39 --- /dev/null +++ b/specs/workspace_spec.rb @@ -0,0 +1,106 @@ +require_relative "test_helper" + +describe "Workspace class" do + describe "Workspace#initialize" do + it "initializes a Workspace object" do + VCR.use_cassette("Workspace") do + response = Workspace.new + expect(response).must_be_instance_of Workspace + end + end + end + + describe "Workspace#select_user" do + it "selects a known user by username" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_user("ngocle") + expect(response.selected.username).must_equal "ngocle" + end + end + + it "selects a known user by slack id" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_user("UH553UM7G") + expect(response.selected.username).must_equal "ngocle" + end + end + + it "raises an Argument if user info is invalid" do + VCR.use_cassette("Workspace") do + response = Workspace.new + expect { response.select_user("tildee") }.must_raise ArgumentError + end + end + end + + describe "Workspace#select_channel" do + it "selects a known channel" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_channel("general") + expect(response.selected.channel_name).must_equal "general" + end + end + + it "selects a known channel by slack id" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_channel("CH41W659D") + expect(response.selected.channel_name).must_equal "general" + end + end + + it "raises an Argument if channel info is invalid" do + VCR.use_cassette("Workspace") do + response = Workspace.new + expect { response.select_channel("starburst") }.must_raise ArgumentError + end + end + end + + describe "Workspace#show_details" do + it "shows details of the selected channel" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_channel("general") + expect(response.show_details).must_be_instance_of Channel + end + end + + it "shows details of the selected user" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_user("ngocle") + expect(response.show_details).must_be_instance_of User + end + end + end + describe "Workspace#send_message" do + it "can send a valid message to a channel" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_channel("general") + status = response.send_message("Hey I can post messages!") + expect(status).must_equal true + end + end + it "raise an argument error when a message is invalid(empty,nil)" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_channel("general") + expect { response.send_message("") }.must_raise ArgumentError + end + end + + it "can send a valid message to an user" do + VCR.use_cassette("Workspace") do + response = Workspace.new + response.select_user("ngocle") + status = response.send_message("Hey I can post messages!") + expect(status).must_equal true + end + end + end +end