Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.gem
*.rbc
.env
/.config
/coverage/
/InstalledFiles
Expand All @@ -11,7 +12,6 @@
/tmp/

# Used by dotenv library to load environment variables.
# .env

## Specific to RubyMotion:
.dat*
Expand Down
31 changes: 31 additions & 0 deletions lib/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require_relative 'recipient'

module Slack
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 "Slack id: #{slack_id}, Name: #{name}, Topic: #{topic}, Member_count: #{member_count}"
end

def self.parse_response(response)
channels = response.parsed_response["channels"].map do |channel|
channel_slack_id = channel["id"]
channel_name = channel["name"]
channel_topic = channel["topic"]["value"]
channel_member_count = channel["members"].length

Channel.new(slack_id: channel_slack_id, name:channel_name, topic: channel_topic, member_count: channel_member_count)
end

return channels
end
end
end
30 changes: 30 additions & 0 deletions lib/recipient.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class SlackApiError < StandardError ; end

module Slack
class Recipient
attr_reader :slack_id, :name

def initialize(slack_id:, name:)
@slack_id = slack_id
@name = name
end

def self.get(url, parameters)
response = HTTParty.get(url, parameters)

unless response.code == 200 && response["ok"]
raise SlackApiError, "Invalid API request with code #{response.code} and message #{response["error"]}."
end

return self.parse_response(response)
end

def details
raise NotImplementedError, "Can't implement from recipient class."
end

def self.parse_response(response)
raise NotImplementedError, "Can't implement recipient class."

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Nice

end
end
end
76 changes: 69 additions & 7 deletions lib/slack.rb
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,11 +1,73 @@
#!/usr/bin/env ruby
require_relative 'user'
require_relative 'workspace'
require_relative 'channel'

def main
puts "Welcome to the Ada Slack CLI!"

# TODO project

puts "Thank you for using the Ada Slack CLI"
workspace = Slack::Workspace.new
should_continue = true

while should_continue
puts "Welcome to Slack! Please choose one of the following:\n1. list users\n2. list channels\n3. select user\n4. select channel\n5. details\n6. send message\n7. set name\n8. set emoji\n9. quit"
input = gets.chomp.downcase

case input
when "1", "list users"
workspace.list_users
when "2", "list channels"
workspace.list_channels
when "3", "select user"
puts "Please enter the name or slack ID of the user you want to select:"
requested_user = gets.chomp

found_user = workspace.select_user(requested_user)
if found_user.class != Slack::User
puts "User was not found."
else
puts "User was selected."
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would break these larger chunks of functionality into little helper methods so that this section of code is easier to parse!

when "4", "select channel"
puts "Please enter the name or slack ID of the channel you want to select:"
requested_channel = gets.chomp

found_channel = workspace.select_channel(requested_channel)
if found_channel.class != Slack::Channel
puts "Channel was not found."
else
puts "Channel was selected."
end
when "5", "details"
if workspace.selected == nil
puts "No user or channel selected."
else
puts workspace.selected.details
end
when "6", "send message"
if workspace.selected == nil
puts "No user or channel selected."
else
puts "Please enter your message: "
message = gets.chomp

workspace.send_message(message)
puts "Your message was sent!"
end
when "7", "set name"
puts "Please enter the name you would like to use: "
new_name = gets.chomp

workspace.set_profile_name(new_name)
when "8", "set emoji"
puts "Please enter the emoji you would like to use: "
new_emoji = gets.chomp

workspace.set_profile_emoji(new_emoji)
when "9", "quit"
puts "Goodbye!"
should_continue = false
else
puts "Please enter a valid menu option"
end
end
end

main if __FILE__ == $PROGRAM_NAME
main if __FILE__ == $PROGRAM_NAME
33 changes: 33 additions & 0 deletions lib/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require_relative 'recipient'

module Slack
class User < Recipient
attr_reader :status_text, :real_name, :status_emoji

def initialize(slack_id:, name:, real_name:, status_text:, status_emoji:)
super(slack_id: slack_id, name: name)

@real_name = real_name
@status_text = status_text
@status_emoji = status_emoji
end

def details
return "Slack id: #{slack_id}, Name: #{name}, Real name: #{real_name}, Status Text: #{status_text}, Status Emoji: #{status_emoji}"
end

def self.parse_response(response)
users = response.parsed_response["members"].map do |member|
member_slack_id = member["id"]
member_name = member["name"]
member_real_name = member["real_name"]
member_status_text = member["profile"]["status_text"]
member_status_emoji = member["profile"]["status_emoji"]

User.new(slack_id: member_slack_id, name: member_name, real_name: member_real_name, status_text: member_status_text, status_emoji: member_status_emoji)
end

return users
end
end
end
102 changes: 102 additions & 0 deletions lib/workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
require_relative 'user'
require_relative 'channel'
require 'dotenv'
require 'httparty'
require 'table_print'

Dotenv.load

module Slack
class Workspace
attr_reader :users, :channels, :selected

BASE_URL = "https://slack.com/api/"
TOKEN = ENV['SLACK_TOKEN']

def initialize
@users = Slack::User.get("#{BASE_URL}/users.list", query: {token: TOKEN})
@channels = Slack::Channel.get("#{BASE_URL}/channels.list", query: {token: TOKEN})
@selected = nil
end

#should this be in workspace or main?
def list_users
tp @users, :real_name, :slack_id, :user_name => {:display_method => :name}
end

def list_channels
tp @channels, :name, :member_count, :slack_id, :topic => {:width => 50}
end

def select_user(requested_user)
found_user = @users.find do |user|
user.name == requested_user || user.slack_id == requested_user
end

@selected = found_user unless found_user == nil

return found_user
end

def select_channel(requested_channel)
found_channel = @channels.find do |channel|
channel.name == requested_channel || channel.slack_id == requested_channel
end

@selected = found_channel unless found_channel == nil

return found_channel
end

def send_message(message)
response = HTTParty.post( "#{BASE_URL}/chat.postMessage", body: { token: TOKEN, channel: selected.slack_id, text: message } )

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, I'd make a class that wraps all the calls to HTTParty on this specific API. That way, you only have to test those messages in isolation, which gives you more direct tests!


unless response.code == 200 && response["ok"]
raise SlackApiError, "Error when sending message to #{selected.name}. Invalid API request with code #{response.code} and message #{response["error"]}."
end

return true
end

def set_profile_name(user_name)
temp_name = @selected.name unless @selected == nil

profile_settings = { token: TOKEN, profile: {"real_name": user_name} }
response = HTTParty.post( "#{BASE_URL}/users.profile.set", headers: { "Content-Type" => "application/json", authorization: "Bearer #{TOKEN}" }, body: profile_settings.to_json )

unless response.code == 200 && response["ok"]
raise SlackApiError, "Error: invalid API request with code #{response.code} and message #{response["error"]}."
end

# reassign users and selected after changing profile information
@users = Slack::User.get( "#{BASE_URL}/users.list", query: { token: TOKEN } )
@selected = select_user(temp_name)

puts "Profile name was changed to #{user_name}."
return true
end

def set_profile_emoji(status_emoji)
temp_name = @selected.name unless @selected == nil

profile_settings = { token: TOKEN, profile: { "status_emoji": status_emoji } }

response = HTTParty.post( "#{BASE_URL}/users.profile.set", headers: { "Content-Type" => "application/json", authorization: "Bearer #{TOKEN}" }, body: profile_settings.to_json )

if response.code == 200 && response["error"] == "profile_status_set_failed_not_emoji_syntax" || response["error"] == "profile_status_set_failed_not_valid_emoji"
puts "Invalid slack emoji."
elsif response.code == 200 && response["ok"] == false
raise SlackApiError, "Error: invalid API request with code #{response.code} and message #{response["error"]}."
else
puts "Status emoji was changed."

# reassign users and selected after changing profile information
@users = Slack::User.get("#{BASE_URL}/users.list", query: {token: TOKEN})
@selected = select_user(temp_name)
end

return true
end
end
end

Loading