diff --git a/.gitignore b/.gitignore
index 3ff4fada..0b7a5469 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@
# Ignore environemnt variables
.env
+lib/.env
+coverage
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/.idea/.rakeTasks b/.idea/.rakeTasks
new file mode 100644
index 00000000..e409da2a
--- /dev/null
+++ b/.idea/.rakeTasks
@@ -0,0 +1,7 @@
+
+
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..b0db9b0f
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..510e7fcc
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..7a98b196
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/slack-cli.iml b/.idea/slack-cli.iml
new file mode 100644
index 00000000..329312d1
--- /dev/null
+++ b/.idea/slack-cli.iml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..94a25f7f
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 00000000..2cadebb6
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,232 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1602024079201
+
+
+ 1602024079201
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/channel.rb b/lib/channel.rb
new file mode 100644
index 00000000..4ab72db9
--- /dev/null
+++ b/lib/channel.rb
@@ -0,0 +1,23 @@
+require_relative 'recipient'
+
+class Channel < Recipient
+ attr_reader :name, :topic, :member_count, :slack_id
+
+ def initialize(slack_id, name, topic, member_count)
+ super(slack_id, name)
+ @topic = topic
+ @member_count = member_count
+
+ raise ArgumentError, "slack ID, name, topic, and member count are all required." unless topic || member_count
+ end
+
+ def self.list_all
+ response = self.get("https://slack.com/api/conversations.list")
+ channels = []
+ response["channels"].each do |channel|
+ channels << Channel.new(channel["id"], channel["name"], channel["topic"]["value"], channel["num_members"])
+ end
+ return channels
+ end
+
+end
\ No newline at end of file
diff --git a/lib/recipient.rb b/lib/recipient.rb
new file mode 100644
index 00000000..2c7df9fa
--- /dev/null
+++ b/lib/recipient.rb
@@ -0,0 +1,47 @@
+require 'httparty'
+#require_relative 'workspace'
+require 'dotenv'
+require 'table_print'
+
+class Recipient
+ Dotenv.load ##inside or outside?
+ BASE_URL = "https://slack.com/api/"
+ SLACK_TOKEN = ENV['SLACK_TOKEN']
+
+ attr_reader :slack_id, :name
+
+ def initialize(slack_id, name)#should we get rid of name????
+ @slack_id = slack_id
+ @name = name
+
+ raise ArgumentError, "slack ID and name are required." unless slack_id || name
+ end
+
+ def self.get(url)
+ return HTTParty.get(url, query: {token: SLACK_TOKEN})
+ end
+
+ def self.list_all
+ raise NotImplementedError, 'Implement me in a child class!'
+ end
+
+ def self.send_message(slack_id, message)
+ raise Exception.new("message is required") if message == ""
+ url = "https://slack.com/api/chat.postMessage"
+ response = HTTParty.post(
+ url,
+ body: {
+ token: SLACK_TOKEN,
+ text: message,
+ channel: slack_id
+ },
+ headers: { 'Content-Type' => 'application/x-www-form-urlencoded' }
+ )
+ if response.code != 200 || response.parsed_response["ok"] == false
+ raise Exception.new("Http request code #{response.code} error #{response.parsed_response["error"]}")
+ end
+ return response
+ end
+
+
+end
\ No newline at end of file
diff --git a/lib/slack.rb b/lib/slack.rb
index 8a0b659b..b4fa0c8d 100755
--- a/lib/slack.rb
+++ b/lib/slack.rb
@@ -1,12 +1,103 @@
#!/usr/bin/env ruby
+require 'httparty'
+require_relative 'workspace'
+require 'dotenv'
+require 'table_print'
+
def main
puts "Welcome to the Ada Slack CLI!"
- workspace = Workspace.new
+ @workspace = Workspace.new
+
+ loop do
+ puts "(~ ̄▽ ̄)~ What would you like to do with CLI? ~( ̄▽ ̄~) \n1. list users \n2. list channels \n3. select user \n4. select channel \n5. detail\n (about the selected user or channel) \n6. send message \n7. quit"
+ input = gets.chomp
- # TODO project
+ case input
+ when "list users", "1"
+ tp @workspace.users
+ puts "\n\n"
+ when "list channels", "2"
+ tp @workspace.channels
+ puts "\n\n"
+ when "select user", "3"
+ select_a_user
+ when "select channel", "4"
+ select_a_channel
+ when "detail", "5"
+ if @workspace.selected == nil
+ puts "ヽ(ˋДˊ)ノ"
+ puts "Please select a user or channel first!"
+ puts "\n\n"
+ else
+ tp @workspace.selected
+ puts "\n\n"
+ end
+ when "send message", "6"
+ write_message
+ puts "\n\n"
+ when "quit", "7"
+ puts "乀(ˉεˉ乀) bye~"
+ break
+ else
+ puts "ヽ(ˋДˊ)ノ"
+ puts "Please enter one of the menu items or their corresponding number values."
+ puts "\n\n"
+ end
+ end
puts "Thank you for using the Ada Slack CLI"
end
+def write_message
+ if @workspace.selected == nil
+ puts "ヽ(ˋДˊ)ノ \nPlease select a user or channel first!"
+ else
+ puts "What is your message?"
+ message = gets.chomp
+ if message == ""
+ puts "ヽ(ˋДˊ)ノ \nNo message was inputted."
+ return false
+ end
+ puts "ヽ(ˋ▽ˊ)ノ \nOk, we sent off your message!" if @workspace.send_message(message).parsed_response["ok"] == true
+ end
+end
+
+def select_a_user
+ loop do
+ puts "What's the user's slack id or username? enter 7 or quit to exit."
+ id_or_name = gets.chomp
+ if id_or_name == "7" || id_or_name == "quit"
+ break
+ end
+ begin
+ @workspace.select_user(id_or_name)
+ rescue Exception
+ puts "ヽ(ˋДˊ)ノ \nPlease enter a valid username or id.\n\n"
+ else
+ puts "ヽ(ˋ▽ˊ)ノ \nOk, #{id_or_name} is selected.\n\n"
+ break
+ end
+ end
+end
+
+def select_a_channel
+ loop do
+ puts "What's the channel's slack id or username? enter 7 or quit to exit."
+ id_or_name = gets.chomp
+ if id_or_name == "7" || id_or_name == "quit"
+ break
+ end
+ begin
+ @workspace.select_channel(id_or_name)
+ rescue Exception
+ puts "ヽ(ˋДˊ)ノ \nPlease enter a valid channel name or id.\n\n"
+ else
+ puts "ヽ(ˋ▽ˊ)ノ \nOk, #{id_or_name} is selected.\n\n"
+ break
+ end
+ end
+end
+
+
main if __FILE__ == $PROGRAM_NAME
\ No newline at end of file
diff --git a/lib/user.rb b/lib/user.rb
new file mode 100644
index 00000000..d8d20e7d
--- /dev/null
+++ b/lib/user.rb
@@ -0,0 +1,23 @@
+require_relative 'recipient'
+
+class User < Recipient
+ attr_reader :name, :real_name, :slack_id
+
+ def initialize(slack_id, name, real_name)
+ super(slack_id, name) #super(name)?????
+ @real_name = real_name
+
+ raise ArgumentError, "real name is required." unless real_name
+ end
+
+ def self.list_all
+ response = self.get("https://slack.com/api/users.list")
+ users = []
+ response["members"].each do |member|
+ users << User.new(member["id"], member["name"], member["real_name"] || member["profile"]["real_name"])
+ end
+ return users
+ end
+end
+
+
diff --git a/lib/workspace.rb b/lib/workspace.rb
new file mode 100644
index 00000000..be33a1f6
--- /dev/null
+++ b/lib/workspace.rb
@@ -0,0 +1,38 @@
+require_relative 'recipient'
+require_relative 'user'
+require_relative 'channel'
+require 'table_print'
+
+class Workspace
+ attr_reader :users, :channels
+ attr_accessor :selected
+
+ def initialize(users: [], channels: [], selected: nil)
+ @users = User.list_all
+ @channels = Channel.list_all
+ @selected = selected
+
+ end
+
+ def select_user(name_or_id)
+ @selected = @users.find {|user| user.slack_id == name_or_id}
+ @selected = @users.find {|user| user.name == name_or_id} unless @selected
+ raise Exception.new("no user found.") unless @selected
+ return @selected
+ end
+
+ def select_channel(name_or_id)
+ @selected = @channels.find {|channel| channel.slack_id == name_or_id}
+ @selected = @channels.find {|channel| channel.name == name_or_id} unless @selected
+ raise Exception.new("no channel found.") unless @selected
+ return @selected
+ end
+
+ def send_message(message)
+ raise Exception.new("nothing selected, please select a user/channel to send to first!") if @selected == nil
+ channel = @selected.slack_id
+ Recipient.send_message(channel, message)
+ # return true
+ end
+end
+
diff --git a/test/cassettes/list_all_channels.yml b/test/cassettes/list_all_channels.yml
new file mode 100644
index 00000000..86f4eb0a
--- /dev/null
+++ b/test/cassettes/list_all_channels.yml
@@ -0,0 +1,74 @@
+---
+http_interactions:
+- request:
+ method: get
+ uri: https://slack.com/api/conversations.list?token=
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Wed, 07 Oct 2020 04:57:19 GMT
+ Server:
+ - Apache
+ X-Slack-Req-Id:
+ - 1b9deaa802fb250110cc11e18f4a5f89
+ X-Oauth-Scopes:
+ - incoming-webhook,channels:read,groups:read,im:read,mpim:read,users:read
+ Access-Control-Expose-Headers:
+ - x-slack-req-id, retry-after
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Slack-Backend:
+ - r
+ X-Content-Type-Options:
+ - nosniff
+ Expires:
+ - Mon, 26 Jul 1997 05:00:00 GMT
+ Cache-Control:
+ - private, no-cache, no-store, must-revalidate
+ X-Xss-Protection:
+ - '0'
+ X-Accepted-Oauth-Scopes:
+ - channels:read,groups:read,mpim:read,im:read,read
+ Access-Control-Allow-Headers:
+ - slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid,
+ x-b3-sampled, x-b3-flags
+ Vary:
+ - Accept-Encoding
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Referrer-Policy:
+ - no-referrer
+ Content-Length:
+ - '693'
+ Content-Type:
+ - application/json; charset=utf-8
+ X-Via:
+ - haproxy-www-ce55,haproxy-edge-pdx-rf66
+ body:
+ encoding: ASCII-8BIT
+ string: '{"ok":true,"channels":[{"id":"C01C16GNVMZ","name":"random","is_channel":true,"is_group":false,"is_im":false,"created":1601965941,"is_archived":false,"is_general":false,"unlinked":0,"name_normalized":"random","is_shared":false,"parent_conversation":null,"creator":"U01C10DATH8","is_ext_shared":false,"is_org_shared":false,"shared_team_ids":["T01C16GNGG3"],"pending_shared":[],"pending_connected_team_ids":[],"is_pending_ext_shared":false,"is_member":false,"is_private":false,"is_mpim":false,"topic":{"value":"cs
+ memes are great!","creator":"U01C10G57NE","last_set":1602023254},"purpose":{"value":"This
+ channel is for... well, everything else. It\u2019s a place for team jokes,
+ spur-of-the-moment ideas, and funny GIFs. Go wild!","creator":"U01C10DATH8","last_set":1601965941},"previous_names":[],"num_members":2},{"id":"C01C761G84U","name":"general","is_channel":true,"is_group":false,"is_im":false,"created":1601965941,"is_archived":false,"is_general":true,"unlinked":0,"name_normalized":"general","is_shared":false,"parent_conversation":null,"creator":"U01C10DATH8","is_ext_shared":false,"is_org_shared":false,"shared_team_ids":["T01C16GNGG3"],"pending_shared":[],"pending_connected_team_ids":[],"is_pending_ext_shared":false,"is_member":false,"is_private":false,"is_mpim":false,"topic":{"value":"We
+ finish wave 1!!","creator":"U01C10DATH8","last_set":1602023247},"purpose":{"value":"This
+ is the one channel that will always include everyone. It\u2019s a great spot
+ for announcements and team-wide conversations.","creator":"U01C10DATH8","last_set":1601965941},"previous_names":[],"num_members":2},{"id":"C01CQR91448","name":"slack-cli","is_channel":true,"is_group":false,"is_im":false,"created":1601966059,"is_archived":false,"is_general":false,"unlinked":0,"name_normalized":"slack-cli","is_shared":false,"parent_conversation":null,"creator":"U01C10DATH8","is_ext_shared":false,"is_org_shared":false,"shared_team_ids":["T01C16GNGG3"],"pending_shared":[],"pending_connected_team_ids":[],"is_pending_ext_shared":false,"is_member":false,"is_private":false,"is_mpim":false,"topic":{"value":"","creator":"","last_set":0},"purpose":{"value":"This
+ *channel* is for working on a project. Hold meetings, share docs, and make
+ decisions together with your team.","creator":"U01C10DATH8","last_set":1601966059},"previous_names":[],"num_members":2}],"response_metadata":{"next_cursor":""}}'
+ recorded_at: Wed, 07 Oct 2020 04:57:19 GMT
+recorded_with: VCR 6.0.0
diff --git a/test/cassettes/list_all_users.yml b/test/cassettes/list_all_users.yml
new file mode 100644
index 00000000..ab11066d
--- /dev/null
+++ b/test/cassettes/list_all_users.yml
@@ -0,0 +1,74 @@
+---
+http_interactions:
+- request:
+ method: get
+ uri: https://slack.com/api/users.list?token=
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Wed, 07 Oct 2020 05:02:00 GMT
+ Server:
+ - Apache
+ X-Slack-Req-Id:
+ - 7cc614de3e4cc73c50fd7015891bd79b
+ X-Oauth-Scopes:
+ - incoming-webhook,channels:read,groups:read,im:read,mpim:read,users:read
+ Access-Control-Expose-Headers:
+ - x-slack-req-id, retry-after
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Slack-Backend:
+ - r
+ X-Content-Type-Options:
+ - nosniff
+ Expires:
+ - Mon, 26 Jul 1997 05:00:00 GMT
+ Cache-Control:
+ - private, no-cache, no-store, must-revalidate
+ X-Xss-Protection:
+ - '0'
+ X-Accepted-Oauth-Scopes:
+ - users:read
+ Access-Control-Allow-Headers:
+ - slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid,
+ x-b3-sampled, x-b3-flags
+ Vary:
+ - Accept-Encoding
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Referrer-Policy:
+ - no-referrer
+ Content-Length:
+ - '1289'
+ Content-Type:
+ - application/json; charset=utf-8
+ X-Via:
+ - haproxy-www-ngke,haproxy-edge-pdx-rshi
+ body:
+ encoding: ASCII-8BIT
+ string: '{"ok":true,"members":[{"id":"USLACKBOT","team_id":"T01C16GNGG3","name":"slackbot","deleted":false,"color":"757575","real_name":"Slackbot","tz":"America\/Los_Angeles","tz_label":"Pacific
+ Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Slackbot","real_name_normalized":"Slackbot","display_name":"Slackbot","display_name_normalized":"Slackbot","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"sv41d8cd98f0","always_active":true,"first_name":"slackbot","last_name":"","image_24":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_24.png","image_32":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_32.png","image_48":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_48.png","image_72":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_72.png","image_192":"https:\/\/a.slack-edge.com\/80588\/marketing\/img\/avatars\/slackbot\/avatar-slackbot.png","image_512":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":0},{"id":"U01BVT790NA","team_id":"T01C16GNGG3","name":"api_project2","deleted":false,"color":"3c989f","real_name":"API
+ project","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"API
+ project","real_name_normalized":"API project","display_name":"","display_name_normalized":"","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g3cef7409b5d","api_app_id":"A01C2R7G4SF","always_active":false,"bot_id":"B01C2RDCQUB","image_24":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"is_app_user":false,"updated":1602006272},{"id":"U01C10DATH8","team_id":"T01C16GNGG3","name":"yjlin789","deleted":false,"color":"9f69e7","real_name":"Jing","tz":"America\/Los_Angeles","tz_label":"Pacific
+ Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Jing","real_name_normalized":"Jing","display_name":"Jing","display_name_normalized":"Jing","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"1581dfb66e14","image_original":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_original.jpg","is_custom_image":true,"first_name":"Jing","last_name":"","image_24":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_72.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_192.jpg","image_512":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_512.jpg","image_1024":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_1024.jpg","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":true,"is_owner":true,"is_primary_owner":true,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":1601966120},{"id":"U01C10G57NE","team_id":"T01C16GNGG3","name":"rencarothers","deleted":false,"color":"4bbe2e","real_name":"Ren
+ Carothers","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Ren
+ Carothers","real_name_normalized":"Ren Carothers","display_name":"Ren Carothers","display_name_normalized":"Ren
+ Carothers","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g53fff90c824","image_24":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":1602018318},{"id":"U01C8PNLVS8","team_id":"T01C16GNGG3","name":"api_project","deleted":true,"profile":{"title":"","phone":"","skype":"","real_name":"API
+ project","real_name_normalized":"API project","display_name":"","display_name_normalized":"","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g12a061ce8c3","api_app_id":"A01BMQV0Z7H","always_active":false,"bot_id":"B01BMSK9J79","image_24":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_bot":true,"is_app_user":false,"updated":1602021025}],"cache_ts":1602046920,"response_metadata":{"next_cursor":""}}'
+ recorded_at: Wed, 07 Oct 2020 05:02:00 GMT
+recorded_with: VCR 6.0.0
diff --git a/test/cassettes/list_all_users_and_channels_for_workspace.yml b/test/cassettes/list_all_users_and_channels_for_workspace.yml
new file mode 100644
index 00000000..32500dd5
--- /dev/null
+++ b/test/cassettes/list_all_users_and_channels_for_workspace.yml
@@ -0,0 +1,145 @@
+---
+http_interactions:
+- request:
+ method: get
+ uri: https://slack.com/api/users.list?token=
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Wed, 07 Oct 2020 17:49:22 GMT
+ Server:
+ - Apache
+ X-Slack-Req-Id:
+ - 28a5a5fa0515e5e4166176ad10bde18d
+ X-Oauth-Scopes:
+ - incoming-webhook,channels:read,groups:read,im:read,mpim:read,users:read
+ Access-Control-Expose-Headers:
+ - x-slack-req-id, retry-after
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Slack-Backend:
+ - r
+ X-Content-Type-Options:
+ - nosniff
+ Expires:
+ - Mon, 26 Jul 1997 05:00:00 GMT
+ Cache-Control:
+ - private, no-cache, no-store, must-revalidate
+ X-Xss-Protection:
+ - '0'
+ X-Accepted-Oauth-Scopes:
+ - users:read
+ Access-Control-Allow-Headers:
+ - slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid,
+ x-b3-sampled, x-b3-flags
+ Vary:
+ - Accept-Encoding
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Referrer-Policy:
+ - no-referrer
+ Content-Length:
+ - '1289'
+ Content-Type:
+ - application/json; charset=utf-8
+ X-Via:
+ - haproxy-www-rog1,haproxy-edge-pdx-ts3v
+ body:
+ encoding: ASCII-8BIT
+ string: '{"ok":true,"members":[{"id":"USLACKBOT","team_id":"T01C16GNGG3","name":"slackbot","deleted":false,"color":"757575","real_name":"Slackbot","tz":"America\/Los_Angeles","tz_label":"Pacific
+ Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Slackbot","real_name_normalized":"Slackbot","display_name":"Slackbot","display_name_normalized":"Slackbot","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"sv41d8cd98f0","always_active":true,"first_name":"slackbot","last_name":"","image_24":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_24.png","image_32":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_32.png","image_48":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_48.png","image_72":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_72.png","image_192":"https:\/\/a.slack-edge.com\/80588\/marketing\/img\/avatars\/slackbot\/avatar-slackbot.png","image_512":"https:\/\/a.slack-edge.com\/80588\/img\/slackbot_512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":0},{"id":"U01BVT790NA","team_id":"T01C16GNGG3","name":"api_project2","deleted":false,"color":"3c989f","real_name":"API
+ project","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"API
+ project","real_name_normalized":"API project","display_name":"","display_name_normalized":"","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g3cef7409b5d","api_app_id":"A01C2R7G4SF","always_active":false,"bot_id":"B01C2RDCQUB","image_24":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/3cef7409b5d39d250a40826935a0e09e.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0011-512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"is_app_user":false,"updated":1602006272},{"id":"U01C10DATH8","team_id":"T01C16GNGG3","name":"yjlin789","deleted":false,"color":"9f69e7","real_name":"Jing","tz":"America\/Los_Angeles","tz_label":"Pacific
+ Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Jing","real_name_normalized":"Jing","display_name":"Jing","display_name_normalized":"Jing","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"1581dfb66e14","image_original":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_original.jpg","is_custom_image":true,"first_name":"Jing","last_name":"","image_24":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_72.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_192.jpg","image_512":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_512.jpg","image_1024":"https:\/\/avatars.slack-edge.com\/2020-10-05\/1409017415330_1581dfb66e143840e9c7_1024.jpg","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":true,"is_owner":true,"is_primary_owner":true,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":1601966120},{"id":"U01C10G57NE","team_id":"T01C16GNGG3","name":"rencarothers","deleted":false,"color":"4bbe2e","real_name":"Ren
+ Carothers","tz":"America\/Los_Angeles","tz_label":"Pacific Daylight Time","tz_offset":-25200,"profile":{"title":"","phone":"","skype":"","real_name":"Ren
+ Carothers","real_name_normalized":"Ren Carothers","display_name":"Ren Carothers","display_name_normalized":"Ren
+ Carothers","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g53fff90c824","image_24":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/53fff90c824dbabb405a72411db7f297.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0021-512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"is_app_user":false,"updated":1602018318},{"id":"U01C8PNLVS8","team_id":"T01C16GNGG3","name":"api_project","deleted":true,"profile":{"title":"","phone":"","skype":"","real_name":"API
+ project","real_name_normalized":"API project","display_name":"","display_name_normalized":"","fields":null,"status_text":"","status_emoji":"","status_expiration":0,"avatar_hash":"g12a061ce8c3","api_app_id":"A01BMQV0Z7H","always_active":false,"bot_id":"B01BMSK9J79","image_24":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=24&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=32&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=72&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/12a061ce8c34f2344cc3c05d80896652.jpg?s=512&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0008-512.png","status_text_canonical":"","team":"T01C16GNGG3"},"is_bot":true,"is_app_user":false,"updated":1602021025}],"cache_ts":1602092962,"response_metadata":{"next_cursor":""}}'
+ recorded_at: Wed, 07 Oct 2020 17:49:22 GMT
+- request:
+ method: get
+ uri: https://slack.com/api/conversations.list?token=
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Wed, 07 Oct 2020 18:58:37 GMT
+ Server:
+ - Apache
+ X-Slack-Req-Id:
+ - 1801e59aedf673ae525b0d093fb52abc
+ X-Oauth-Scopes:
+ - incoming-webhook,channels:read,groups:read,im:read,mpim:read,users:read
+ Access-Control-Expose-Headers:
+ - x-slack-req-id, retry-after
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Slack-Backend:
+ - r
+ X-Content-Type-Options:
+ - nosniff
+ Expires:
+ - Mon, 26 Jul 1997 05:00:00 GMT
+ Cache-Control:
+ - private, no-cache, no-store, must-revalidate
+ X-Xss-Protection:
+ - '0'
+ X-Accepted-Oauth-Scopes:
+ - channels:read,groups:read,mpim:read,im:read,read
+ Access-Control-Allow-Headers:
+ - slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid,
+ x-b3-sampled, x-b3-flags
+ Vary:
+ - Accept-Encoding
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Referrer-Policy:
+ - no-referrer
+ Content-Length:
+ - '693'
+ Content-Type:
+ - application/json; charset=utf-8
+ X-Via:
+ - haproxy-www-9bli,haproxy-edge-pdx-ts3v
+ body:
+ encoding: ASCII-8BIT
+ string: '{"ok":true,"channels":[{"id":"C01C16GNVMZ","name":"random","is_channel":true,"is_group":false,"is_im":false,"created":1601965941,"is_archived":false,"is_general":false,"unlinked":0,"name_normalized":"random","is_shared":false,"parent_conversation":null,"creator":"U01C10DATH8","is_ext_shared":false,"is_org_shared":false,"shared_team_ids":["T01C16GNGG3"],"pending_shared":[],"pending_connected_team_ids":[],"is_pending_ext_shared":false,"is_member":false,"is_private":false,"is_mpim":false,"topic":{"value":"cs
+ memes are great!","creator":"U01C10G57NE","last_set":1602023254},"purpose":{"value":"This
+ channel is for... well, everything else. It\u2019s a place for team jokes,
+ spur-of-the-moment ideas, and funny GIFs. Go wild!","creator":"U01C10DATH8","last_set":1601965941},"previous_names":[],"num_members":2},{"id":"C01C761G84U","name":"general","is_channel":true,"is_group":false,"is_im":false,"created":1601965941,"is_archived":false,"is_general":true,"unlinked":0,"name_normalized":"general","is_shared":false,"parent_conversation":null,"creator":"U01C10DATH8","is_ext_shared":false,"is_org_shared":false,"shared_team_ids":["T01C16GNGG3"],"pending_shared":[],"pending_connected_team_ids":[],"is_pending_ext_shared":false,"is_member":false,"is_private":false,"is_mpim":false,"topic":{"value":"We
+ finish wave 1!!","creator":"U01C10DATH8","last_set":1602023247},"purpose":{"value":"This
+ is the one channel that will always include everyone. It\u2019s a great spot
+ for announcements and team-wide conversations.","creator":"U01C10DATH8","last_set":1601965941},"previous_names":[],"num_members":2},{"id":"C01CQR91448","name":"slack-cli","is_channel":true,"is_group":false,"is_im":false,"created":1601966059,"is_archived":false,"is_general":false,"unlinked":0,"name_normalized":"slack-cli","is_shared":false,"parent_conversation":null,"creator":"U01C10DATH8","is_ext_shared":false,"is_org_shared":false,"shared_team_ids":["T01C16GNGG3"],"pending_shared":[],"pending_connected_team_ids":[],"is_pending_ext_shared":false,"is_member":false,"is_private":false,"is_mpim":false,"topic":{"value":"","creator":"","last_set":0},"purpose":{"value":"This
+ *channel* is for working on a project. Hold meetings, share docs, and make
+ decisions together with your team.","creator":"U01C10DATH8","last_set":1601966059},"previous_names":[],"num_members":2}],"response_metadata":{"next_cursor":""}}'
+ recorded_at: Wed, 07 Oct 2020 18:58:37 GMT
+recorded_with: VCR 6.0.0
diff --git a/test/cassettes/recipient_send_message.yml b/test/cassettes/recipient_send_message.yml
new file mode 100644
index 00000000..503d4981
--- /dev/null
+++ b/test/cassettes/recipient_send_message.yml
@@ -0,0 +1,70 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://slack.com/api/chat.postMessage
+ body:
+ encoding: UTF-8
+ string: token=&text=Test%20Message&channel=C01C16GNVMZ
+ headers:
+ Content-Type:
+ - application/x-www-form-urlencoded
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Thu, 08 Oct 2020 19:10:46 GMT
+ Server:
+ - Apache
+ X-Slack-Req-Id:
+ - 0d3d260dd851a23b3621f14996905152
+ X-Oauth-Scopes:
+ - incoming-webhook,channels:read,groups:read,im:read,mpim:read,users:read,chat:write
+ Access-Control-Expose-Headers:
+ - x-slack-req-id, retry-after
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Slack-Backend:
+ - r
+ X-Content-Type-Options:
+ - nosniff
+ Expires:
+ - Mon, 26 Jul 1997 05:00:00 GMT
+ Cache-Control:
+ - private, no-cache, no-store, must-revalidate
+ X-Xss-Protection:
+ - '0'
+ X-Accepted-Oauth-Scopes:
+ - chat:write
+ Access-Control-Allow-Headers:
+ - slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid,
+ x-b3-sampled, x-b3-flags
+ Vary:
+ - Accept-Encoding
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Referrer-Policy:
+ - no-referrer
+ Content-Length:
+ - '320'
+ Content-Type:
+ - application/json; charset=utf-8
+ X-Via:
+ - haproxy-www-a01j,haproxy-edge-pdx-1nke
+ body:
+ encoding: ASCII-8BIT
+ string: '{"ok":true,"channel":"C01C16GNVMZ","ts":"1602184246.000600","message":{"bot_id":"B01C2RDCQUB","type":"message","text":"Test
+ Message","user":"U01BVT790NA","ts":"1602184246.000600","team":"T01C16GNGG3","bot_profile":{"id":"B01C2RDCQUB","deleted":false,"name":"API
+ project","updated":1602006272,"app_id":"A01C2R7G4SF","icons":{"image_36":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/bot_36.png","image_48":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/bot_48.png","image_72":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/service_72.png"},"team_id":"T01C16GNGG3"}}}'
+ recorded_at: Thu, 08 Oct 2020 19:10:46 GMT
+recorded_with: VCR 6.0.0
diff --git a/test/cassettes/send_message_to_channel.yml b/test/cassettes/send_message_to_channel.yml
new file mode 100644
index 00000000..a411d13f
--- /dev/null
+++ b/test/cassettes/send_message_to_channel.yml
@@ -0,0 +1,70 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://slack.com/api/chat.postMessage
+ body:
+ encoding: UTF-8
+ string: token=&text=Test%20Message&channel=C01C16GNVMZ
+ headers:
+ Content-Type:
+ - application/x-www-form-urlencoded
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Thu, 08 Oct 2020 19:02:19 GMT
+ Server:
+ - Apache
+ X-Slack-Req-Id:
+ - d4d1cea63b4e25ea64a20afd1801c545
+ X-Oauth-Scopes:
+ - incoming-webhook,channels:read,groups:read,im:read,mpim:read,users:read,chat:write
+ Access-Control-Expose-Headers:
+ - x-slack-req-id, retry-after
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Slack-Backend:
+ - r
+ X-Content-Type-Options:
+ - nosniff
+ Expires:
+ - Mon, 26 Jul 1997 05:00:00 GMT
+ Cache-Control:
+ - private, no-cache, no-store, must-revalidate
+ X-Xss-Protection:
+ - '0'
+ X-Accepted-Oauth-Scopes:
+ - chat:write
+ Access-Control-Allow-Headers:
+ - slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid,
+ x-b3-sampled, x-b3-flags
+ Vary:
+ - Accept-Encoding
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Referrer-Policy:
+ - no-referrer
+ Content-Length:
+ - '321'
+ Content-Type:
+ - application/json; charset=utf-8
+ X-Via:
+ - haproxy-www-3qgr,haproxy-edge-pdx-jcbi
+ body:
+ encoding: ASCII-8BIT
+ string: '{"ok":true,"channel":"C01C16GNVMZ","ts":"1602183739.000500","message":{"bot_id":"B01C2RDCQUB","type":"message","text":"Test
+ Message","user":"U01BVT790NA","ts":"1602183739.000500","team":"T01C16GNGG3","bot_profile":{"id":"B01C2RDCQUB","deleted":false,"name":"API
+ project","updated":1602006272,"app_id":"A01C2R7G4SF","icons":{"image_36":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/bot_36.png","image_48":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/bot_48.png","image_72":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/service_72.png"},"team_id":"T01C16GNGG3"}}}'
+ recorded_at: Thu, 08 Oct 2020 19:02:19 GMT
+recorded_with: VCR 6.0.0
diff --git a/test/cassettes/send_message_to_user.yml b/test/cassettes/send_message_to_user.yml
new file mode 100644
index 00000000..17050899
--- /dev/null
+++ b/test/cassettes/send_message_to_user.yml
@@ -0,0 +1,70 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://slack.com/api/chat.postMessage
+ body:
+ encoding: UTF-8
+ string: token=&text=Test%20Message&channel=U01C10G57NE
+ headers:
+ Content-Type:
+ - application/x-www-form-urlencoded
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Thu, 08 Oct 2020 19:02:19 GMT
+ Server:
+ - Apache
+ X-Slack-Req-Id:
+ - 1e850e2f756012c2ee536306a94751d2
+ X-Oauth-Scopes:
+ - incoming-webhook,channels:read,groups:read,im:read,mpim:read,users:read,chat:write
+ Access-Control-Expose-Headers:
+ - x-slack-req-id, retry-after
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Slack-Backend:
+ - r
+ X-Content-Type-Options:
+ - nosniff
+ Expires:
+ - Mon, 26 Jul 1997 05:00:00 GMT
+ Cache-Control:
+ - private, no-cache, no-store, must-revalidate
+ X-Xss-Protection:
+ - '0'
+ X-Accepted-Oauth-Scopes:
+ - chat:write
+ Access-Control-Allow-Headers:
+ - slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid,
+ x-b3-sampled, x-b3-flags
+ Vary:
+ - Accept-Encoding
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Referrer-Policy:
+ - no-referrer
+ Content-Length:
+ - '323'
+ Content-Type:
+ - application/json; charset=utf-8
+ X-Via:
+ - haproxy-www-ur5l,haproxy-edge-pdx-dhzt
+ body:
+ encoding: ASCII-8BIT
+ string: '{"ok":true,"channel":"D01CSEP0M5E","ts":"1602183739.000100","message":{"bot_id":"B01C2RDCQUB","type":"message","text":"Test
+ Message","user":"U01BVT790NA","ts":"1602183739.000100","team":"T01C16GNGG3","bot_profile":{"id":"B01C2RDCQUB","deleted":false,"name":"API
+ project","updated":1602006272,"app_id":"A01C2R7G4SF","icons":{"image_36":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/bot_36.png","image_48":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/bot_48.png","image_72":"https:\/\/a.slack-edge.com\/80588\/img\/plugins\/app\/service_72.png"},"team_id":"T01C16GNGG3"}}}'
+ recorded_at: Thu, 08 Oct 2020 19:02:19 GMT
+recorded_with: VCR 6.0.0
diff --git a/test/channel_test.rb b/test/channel_test.rb
new file mode 100644
index 00000000..768c2525
--- /dev/null
+++ b/test/channel_test.rb
@@ -0,0 +1,64 @@
+require_relative 'test_helper'
+
+describe "Initializer" do
+ before do
+ @channel1 = Channel.new(123, "snacks", "ice cream", 5)
+ end
+
+ it "is an instance of User" do
+ expect(@channel1).must_be_kind_of Channel
+ end
+
+ it "username must be a string" do
+ expect(@channel1.name).must_be_kind_of String
+ end
+
+ it "real name must be a string" do
+ expect(@channel1.topic).must_be_kind_of String
+ end
+
+ it "Slack ID must be a integer" do
+ expect(@channel1.slack_id).must_be_kind_of Integer
+ end
+
+ it "member count must be a integer" do
+ expect(@channel1.member_count).must_be_kind_of Integer
+ end
+
+ it "raise error when slack is or name is missing" do
+ expect{Channel.new(123)}.must_raise ArgumentError
+ expect{Channel.new(name: "Totoro")}.must_raise ArgumentError
+ end
+
+ it "raise error when topic or member count is missing" do
+ expect{Channel.new(123, "Totoro", member_count: 5)}.must_raise ArgumentError
+ expect{Channel.new(123, "snacks", "ice cream")}.must_raise ArgumentError
+ end
+end
+
+describe "list_all" do
+
+ it "should return all the channels" do
+ VCR.use_cassette("list_all_channels") do
+ response = Channel.list_all
+
+ expect(response.length).must_equal 3
+ end
+
+ end
+
+ it "return the correct info for the first" do
+ VCR.use_cassette("list_all_channels") do
+ response = Channel.list_all
+ expect(response.first.name).must_equal "random"
+ end
+ end
+
+ it "return the correct info for the last" do
+ VCR.use_cassette("list_all_channels") do
+ response = Channel.list_all
+ expect(response.last.name).must_equal "slack-cli"
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/test/recipient_test.rb b/test/recipient_test.rb
new file mode 100644
index 00000000..061d78e5
--- /dev/null
+++ b/test/recipient_test.rb
@@ -0,0 +1,44 @@
+require_relative 'test_helper'
+
+describe "Initializer" do
+ before do
+ @recipient1 = Recipient.new(123, "Totoro")
+ end
+
+ it "is an instance of User" do
+ expect(@recipient1).must_be_kind_of Recipient
+ end
+
+ it "username must be a string" do
+ expect(@recipient1.name).must_be_kind_of String
+ end
+
+ it "Slack ID must be a integer" do
+ expect(@recipient1.slack_id).must_be_kind_of Integer
+ end
+
+ it "raise error when slack is or name is missing" do
+ expect{Recipient.new(123)}.must_raise ArgumentError
+ expect{Recipient.new(name: "Totoro")}.must_raise ArgumentError
+ end
+end
+
+describe "send_message" do
+ before do
+ @recipient1 = Recipient.new("C01C16GNVMZ","random")
+ @message = "Test Message"
+ # end
+ end
+
+ it "successfully sends a message" do
+ VCR.use_cassette("recipient_send_message") do
+ expect(Recipient.send_message(@recipient1.slack_id, @message).parsed_response["ok"]).must_equal true
+ end
+ end
+
+ it "raise an error if message is nil" do
+ @message = nil
+ expect{@recipient1.send_message(@message)}.must_raise Exception
+ end
+
+end
\ No newline at end of file
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 1fcf2bab..78c33acc 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -8,6 +8,9 @@
require 'minitest/reporters'
require 'minitest/skip_dsl'
require 'vcr'
+require_relative '../lib/workspace'
+require_relative '../lib/user'
+require_relative '../lib/channel'
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
@@ -23,7 +26,9 @@
: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
}
-
+ config.filter_sensitive_data("") do
+ ENV["SLACK_TOKEN"]
+ end
# Don't leave our token lying around in a cassette file.
end
diff --git a/test/user_test.rb b/test/user_test.rb
new file mode 100644
index 00000000..33870b06
--- /dev/null
+++ b/test/user_test.rb
@@ -0,0 +1,58 @@
+require_relative 'test_helper'
+
+describe "Initializer" do
+ before do
+ @user1 = User.new(123, "Totoro", "Ghibli")
+ end
+
+ it "is an instance of User" do
+ expect(@user1).must_be_kind_of User
+ end
+
+ it "username must be a string" do
+ expect(@user1.name).must_be_kind_of String
+ end
+
+ it "real name must be a string" do
+ expect(@user1.real_name).must_be_kind_of String
+ end
+
+ it "Slack ID must be a integer" do
+ expect(@user1.slack_id).must_be_kind_of Integer
+ end
+
+ it "raise error when slack is or name is missing" do
+ expect{User.new(123)}.must_raise ArgumentError
+ expect{User.new(name: "Totoro")}.must_raise ArgumentError
+ end
+
+ it "raise error when real name is missing" do
+ expect{User.new(123, "Totoro")}.must_raise ArgumentError
+ end
+
+end
+
+describe "list_all" do
+
+ it "should return all the users" do
+ VCR.use_cassette("list_all_users") do
+ response = User.list_all
+ expect(response.length).must_equal 5
+ end
+ end
+
+ it "return the correct info for the first" do
+ VCR.use_cassette("list_all_users") do
+ response = User.list_all
+ expect(response.first.name).must_equal "slackbot"
+ end
+ end
+
+ it "return the correct info for the last" do
+ VCR.use_cassette("list_all_users") do
+ response = User.list_all
+ expect(response.last.name).must_equal "api_project"
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/test/workspace_test.rb b/test/workspace_test.rb
new file mode 100644
index 00000000..7d6956b1
--- /dev/null
+++ b/test/workspace_test.rb
@@ -0,0 +1,74 @@
+require_relative 'test_helper'
+
+describe "Initializer" do
+ before do
+ VCR.use_cassette("list_all_users_and_channels_for_workspace") do
+ @workspace1 = Workspace.new
+ end
+ end
+
+ it "is an instance of Workspace" do
+ expect(@workspace1).must_be_kind_of Workspace
+ end
+
+ it "uses must be an array" do
+ expect(@workspace1.users).must_be_kind_of Array
+ end
+
+ it "channels must be an array" do
+ expect(@workspace1.channels).must_be_kind_of Array
+ end
+
+end
+
+describe "select user or channel" do
+ before do
+ VCR.use_cassette("list_all_users_and_channels_for_workspace") do
+ @workspace1 = Workspace.new
+ end
+ end
+ it "return correct user" do
+ expect(@workspace1.select_user("yjlin789")).must_be_kind_of User
+ expect(@workspace1.select_user("yjlin789").name).must_equal "yjlin789"
+ expect(@workspace1.select_user("USLACKBOT").name).must_equal "slackbot"
+ end
+ it "return correct channel" do
+ expect(@workspace1.select_channel("random")).must_be_kind_of Channel
+ expect(@workspace1.select_channel("random").name).must_equal "random"
+ expect(@workspace1.select_channel("C01C761G84U").name).must_equal "general"
+ end
+end
+
+describe "send_message" do
+ before do
+ VCR.use_cassette("list_all_users_and_channels_for_workspace") do
+ @workspace1 = Workspace.new
+ @message = "Test Message"
+ @workspace1.selected = Recipient.new("C01C16GNVMZ","random")
+ end
+ end
+
+ it "successfully sends a message to a channel" do
+ VCR.use_cassette("send_message_to_channel") do
+ expect(@workspace1.send_message(@message).parsed_response["ok"]).must_equal true
+ end
+ end
+
+ it "successfully sends a message to a user" do
+ VCR.use_cassette("send_message_to_user") do
+ @workspace1.selected = Recipient.new("U01C10G57NE","rencarothers")
+ expect(@workspace1.send_message(@message).parsed_response["ok"]).must_equal true
+ end
+ end
+
+ it "raise an error if message is nil" do
+ @message = nil
+ expect{@workspace1.send_message(@message)}.must_raise Exception
+ end
+
+ it "if user or channel is not selected, raises an error" do
+ @workspace1.selected = nil
+ expect{@workspace1.send_message(@message)}.must_raise Exception
+ end
+
+end