-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Anna and Ida - Slack CLI #9
base: master
Are you sure you want to change the base?
Changes from all commits
221ac6a
32143c2
cabd626
2a94ff7
99d6a33
ae12992
c164243
1807024
0b890a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"url": "https://floobits.com/idagoitom/slack-cli" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
extern | ||
node_modules | ||
tmp | ||
vendor | ||
.idea/workspace.xml | ||
.idea/misc.xml |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,5 @@ | |
|
||
# Ignore environemnt variables | ||
.env | ||
.floo | ||
.flooignore |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
require_relative 'recipient' | ||
|
||
class Channel < Recipient | ||
attr_reader :topic, :member_count | ||
|
||
def initialize(slack_id:, name:, topic:, member_count:) | ||
super(slack_id: slack_id, name: name) | ||
@topic = topic | ||
@member_count = member_count | ||
end | ||
|
||
def details | ||
return "Name: #{@name}, ID: #{@slack_id}, Topic: #{@topic}, Member count: #{@member_count}" | ||
end | ||
|
||
def self.list_all | ||
response = self.get(CHANNELS_URL, PARAMS) | ||
response["channels"].map do |channel| | ||
Channel.new( | ||
slack_id: channel["id"], | ||
name: channel["name"], | ||
topic: channel["topic"]["value"], | ||
member_count: channel["num_members"] | ||
) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
require 'httparty' | ||
require 'dotenv' | ||
|
||
Dotenv.load | ||
|
||
class SlackApiError < StandardError; end | ||
|
||
class Recipient | ||
USERS_URL = 'https://slack.com/api/users.list' | ||
CHANNELS_URL = 'https://slack.com/api/conversations.list' | ||
MESSAGE_URL = 'https://slack.com/api/chat.postMessage' | ||
PARAMS = 'SLACK_API_TOKEN' | ||
SLACK_BOT_TOKEN = 'SLACK_BOT_API_TOKEN' | ||
Comment on lines
+9
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Smart for making these into constants!
Comment on lines
+12
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These constants end up being kind of confusing throughout your project. What does the name I'm wondering if there's some confusion about constants, and why I might be confused by your use of constants. If that's the case, let me know and I can go over this stuff! If this comment makes sense to y'all and you see how it feels messy, then I'd encourage y'all to see code like this in the future and refactor and simplify! It might have been more direct if you all only used one API token in this project consistently, and using one syntax consistently. |
||
|
||
attr_reader :slack_id, :name | ||
|
||
def initialize(slack_id: nil, name: nil) | ||
@slack_id = slack_id | ||
@name = name | ||
end | ||
|
||
def self.get(url, params) | ||
sleep(0.5) | ||
HTTParty.get(url, query: {token: ENV[params]}) | ||
end | ||
|
||
def send_message(message) | ||
sleep(0.5) | ||
|
||
response = HTTParty.post( | ||
MESSAGE_URL, | ||
body: { | ||
token: ENV[SLACK_BOT_TOKEN], | ||
channel: @slack_id, | ||
text: message | ||
}, | ||
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' } | ||
) | ||
|
||
unless response.code == 200 && response.parsed_response["ok"] | ||
raise SlackApiError, "Error when posting #{message} to #{@slack_id}, error: #{response.parsed_response["error"]}" | ||
end | ||
return response | ||
end | ||
|
||
def details | ||
raise NotImplementedError, 'Implement me in a child class!' | ||
end | ||
|
||
def self.list_all | ||
raise NotImplementedError, 'Implement me in a child class!' | ||
end | ||
|
||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,52 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require 'table_print' | ||
require_relative 'workspace' | ||
|
||
def main | ||
puts "Welcome to the Ada Slack CLI!" | ||
|
||
workspace = Workspace.new | ||
|
||
# TODO project | ||
puts "We have #{workspace.channels.size} channels and #{workspace.users.size} users loaded.\n" | ||
|
||
end_program = false | ||
until end_program | ||
puts "\nThere are several options to interact with this program. Please pick one: " | ||
puts "1. list users" | ||
puts "2. list channels" | ||
puts "3. select user" | ||
puts "4. select channel" | ||
puts "5. details" | ||
puts "6. send message" | ||
puts "7. quit\n\n" | ||
|
||
puts "Thank you for using the Ada Slack CLI" | ||
user_input = gets.chomp | ||
|
||
case user_input | ||
when "list users" | ||
tp User.list_all, "real_name", "slack_id", "name" | ||
when "list channels" | ||
tp Channel.list_all, "name", "topic", "slack_id", "member_count" | ||
when "select user" | ||
puts "Please enter a user name or user id:" | ||
select_user_input = gets.chomp | ||
workspace.select_user(select_user_input) | ||
when "select channel" | ||
puts "Select a channel name or id:" | ||
channel_input = gets.chomp | ||
workspace.select_channel(channel_input) | ||
when "details" | ||
puts workspace.show_details | ||
when "send message" | ||
workspace.send_message | ||
when "quit" | ||
puts "Thank you for using the Ada Slack CLI" | ||
end_program = true | ||
end | ||
end | ||
end | ||
|
||
main if __FILE__ == $PROGRAM_NAME | ||
main if __FILE__ == $PROGRAM_NAME | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
require_relative 'recipient' | ||
|
||
class User < Recipient | ||
attr_reader :real_name | ||
|
||
def initialize(slack_id:, name:, real_name:) | ||
super(slack_id: slack_id, name: name) | ||
@real_name = real_name | ||
end | ||
|
||
def details | ||
return "Name: #{@real_name}, ID: #{@slack_id}, Username: #{@name}" | ||
end | ||
|
||
def self.list_all | ||
response = self.get(USERS_URL, PARAMS) | ||
|
||
response["members"].map do |member| | ||
User.new( | ||
slack_id: member["id"], | ||
name: member["name"], | ||
real_name: member["real_name"] | ||
) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
require_relative 'user' | ||
require_relative 'channel' | ||
|
||
class Workspace | ||
attr_reader :users, :channels, :selected | ||
|
||
def initialize | ||
@users = User.list_all | ||
@channels = Channel.list_all | ||
@selected = nil | ||
end | ||
|
||
def select_user(user) | ||
@users.each do |member| | ||
if user == member.slack_id || user == member.name | ||
@selected = member | ||
end | ||
end | ||
|
||
if @selected.nil? | ||
puts "This user was not found." | ||
end | ||
|
||
return @selected | ||
end | ||
|
||
def select_channel(name) | ||
@channels.each do |channel| | ||
if name == channel.name || name == channel.slack_id | ||
@selected = channel | ||
end | ||
end | ||
|
||
if @selected.nil? | ||
puts "This channel was not found." | ||
end | ||
|
||
return @selected | ||
end | ||
|
||
def show_details | ||
if @selected.nil? | ||
puts "No recipient is currently selected." | ||
return | ||
end | ||
|
||
@selected.details | ||
end | ||
|
||
def send_message | ||
if @selected.nil? | ||
puts "No recipient is currently selected to send a message to." | ||
return | ||
end | ||
|
||
puts "Please enter a message:" | ||
message = gets.chomp | ||
|
||
@selected.send_message(message) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mentioned this in the feedback table, but just to repeat: If
response
on lin 17 doesn't come back with a success of 200, then on line 18,response["channels"]
will likely benil
, andresponse["channels"].map
will say"There is no method map for nil"
, and break!You all had a good pattern in the
send_message
method, where you checked the response code and raised an error, and also tested for that case.