Skip to content

Commit

Permalink
use help scope for providing help attrs
Browse files Browse the repository at this point in the history
  • Loading branch information
accessd committed May 5, 2016
1 parent 50d9203 commit 239485b
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 104 deletions.
4 changes: 0 additions & 4 deletions examples/market/marketbot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
require 'yahoo-finance'

class MarketBot < SlackRubyBot::Bot
title 'MarketBot'
desc 'Shows the last finance quotes'
long_desc 'Understands commands like: How\'s AMZN today?'

scan(/([A-Z]{2,5}+)/) do |client, data, stocks|
YahooFinance::Client.new.quotes(stocks, [:name, :symbol, :last_trade_price, :change, :change_in_percent]).each do |quote|
next if quote.symbol == 'N/A'
Expand Down
4 changes: 0 additions & 4 deletions examples/minimal/pongbot.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
require 'slack-ruby-bot'

class Bot < SlackRubyBot::Bot
title 'ping'
desc 'Sends you pong.'
long_desc ''

command 'ping' do |client, data, _match|
client.say(text: 'pong', channel: data.channel)
end
Expand Down
17 changes: 14 additions & 3 deletions examples/weather/weatherbot.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
require 'slack-ruby-bot'

class WeatherBot < SlackRubyBot::Bot
title 'WeatherBot'
desc 'Shows how the weather'
long_desc 'Command format: How is the weather in Paris?'
help do
title 'Weather Bot'
desc 'This bot tells you the weather.'

command 'clouds' do
desc "Tells you how many clouds there're above you."
end

command "What's the weather in <city>?" do
desc 'Tells you the weather in a <city>.'
long_desc "Accurate 10 Day Weather Forecasts for thousands of places around the World.\n" \
"We provide detailed Weather Forecasts over a 10 day period updated four times a day."
end
end

match(/^How is the weather in (?<location>\w*)\?$/i) do |client, data, match|
client.say(channel: data.channel, text: "The weather in #{match[:location]} is nice.")
Expand Down
2 changes: 1 addition & 1 deletion lib/slack-ruby-bot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ def config
end

require 'slack-ruby-client'
require 'slack-ruby-bot/support/commands_helper'
require 'slack-ruby-bot/commands'
require 'slack-ruby-bot/client'
require 'slack-ruby-bot/server'
require 'slack-ruby-bot/support/commands_helper'
require 'slack-ruby-bot/app'
require 'slack-ruby-bot/bot'
1 change: 0 additions & 1 deletion lib/slack-ruby-bot/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ def initialize(options = {})
Slack.configure do |config|
config.token = SlackRubyBot.config.token
end
CommandsHelper.validate_attrs if SlackRubyBot.config.help_attrs_required?
super
end

Expand Down
18 changes: 5 additions & 13 deletions lib/slack-ruby-bot/commands/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module SlackRubyBot
module Commands
class Base
include Loggable
class_attribute :routes, :command_name, :command_desc, :command_long_desc
class_attribute :routes

class << self
def send_message(client, channel, text, options = {})
Expand All @@ -24,6 +24,10 @@ def send_gif(client, channel, keywords, options = {})
client.say(options.merge(channel: channel, text: '', gif: keywords))
end

def help(&block)
CommandsHelper.instance.capture_help(name, &block)
end

def default_command_name
name && name.split(':').last.downcase
end
Expand Down Expand Up @@ -78,18 +82,6 @@ def scan(match, &block)
self.routes[match] = { match_method: :scan, call: block }
end

def title(title)
self.command_name = title
end

def desc(desc)
self.command_desc = desc
end

def long_desc(long_desc)
self.command_long_desc = long_desc
end

private

def parse(client, data)
Expand Down
19 changes: 10 additions & 9 deletions lib/slack-ruby-bot/commands/help.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
module SlackRubyBot
module Commands
class Help < Base
title 'help'
desc 'Shows help information.'
long_desc ''
help do
title 'help'
desc 'Shows help information.'
end

command 'help' do |client, data, match|
command = match[:expression]

text = if command.present?
CommandsHelper.command_full_desc(command)
CommandsHelper.instance.command_full_desc(command)
else
general_text
end
Expand All @@ -22,13 +23,13 @@ class << self
private

def general_text
bots_descs = CommandsHelper.all_bots_descs
command_descs = CommandsHelper.all_commands_descs
bot_desc = CommandsHelper.instance.bot_desc_and_commands
other_commands_descs = CommandsHelper.instance.other_commands_descs
<<TEXT
#{bots_descs.join("\n")}
#{bot_desc.join("\n")}
*Possible commands:*
#{command_descs.join("\n")}
*Other commands:*
#{other_commands_descs.join("\n")}
For getting description of the command use: *help <command>*
Expand Down
7 changes: 4 additions & 3 deletions lib/slack-ruby-bot/commands/hi.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
module SlackRubyBot
module Commands
class Hi < Base
title 'hi'
desc 'Says hello.'
long_desc 'When a user types "hi" the bot will reply "hello". This helps everyone stay polite.'
help do
title 'hi'
desc 'Says hello.'
end

def self.call(client, data, _match)
client.say(channel: data.channel, text: "Hi <@#{data.user}>!", gif: 'hi')
Expand Down
7 changes: 1 addition & 6 deletions lib/slack-ruby-bot/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@ module SlackRubyBot
module Config
extend self

ATTRS = [:token, :url, :aliases, :user, :user_id, :team, :team_id, :allow_message_loops, :send_gifs,
:help_attrs_required].freeze
ATTRS = [:token, :url, :aliases, :user, :user_id, :team, :team_id, :allow_message_loops, :send_gifs].freeze
attr_accessor(*ATTRS)

def allow_message_loops?
allow_message_loops
end

def help_attrs_required?
help_attrs_required
end

def send_gifs?
v = boolean_from_env('SLACK_RUBY_BOT_SEND_GIFS')
v.nil? ? (send_gifs.nil? || send_gifs) : v
Expand Down
143 changes: 83 additions & 60 deletions lib/slack-ruby-bot/support/commands_helper.rb
Original file line number Diff line number Diff line change
@@ -1,79 +1,102 @@
require 'singleton'

module SlackRubyBot
class CommandHelpAttrs
attr_accessor :command_name, :command_desc, :command_long_desc
attr_reader :class_name, :commands

def initialize(class_name)
@class_name = class_name
@commands = []
end

def title(title)
self.command_name = title
end

def desc(desc)
self.command_desc = desc
end

def long_desc(long_desc)
self.command_long_desc = long_desc
end

def command(title, &block)
@commands << self.class.new(class_name).tap { |k| k.title(title); k.instance_eval &block }
end
end

class CommandsHelper
BUILTIN_COMMAND_CLASSES = [SlackRubyBot::Commands::Help, SlackRubyBot::Commands::Hi].freeze
HELP_ATTR_METHODS_MAP = {
command_name: :title,
command_desc: :desc,
command_long_desc: :long_desc
}.freeze

class << self
def validate_attrs
all_command_classes.each do |k|
HELP_ATTR_METHODS_MAP.each do |attr, setter_method|
raise "#{k}: #{setter_method} is not present" if k.public_send(attr).nil?
end
end
end
include Singleton
attr_reader :commands_help_attrs

def all_bots_descs
commands_info(bot_classes).map do |command_info|
"#{command_name_and_desc(command_info)}\n#{command_info[:long_desc]}"
end
end
def initialize
@commands_help_attrs = []
end

def all_commands_descs
commands_info(command_classes_only).map do |command_info|
command_name_and_desc(command_info)
end
end
def capture_help(class_name, &block)
k = CommandHelpAttrs.new(class_name)
k.instance_eval(&block)
@commands_help_attrs << k
end

def command_full_desc(name)
info = commands_info(command_classes_only).find { |command_info| command_info[:title] == name }
return "There's no command #{name}" unless info
return "There's no description for command #{name}" if info[:long_desc].blank?
"#{command_name_and_desc(info)}\n\n#{info[:long_desc]}"
def bot_desc_and_commands
collect_help_attrs(bot_help_attrs) do |help_attrs|
bot_commands_descs = collect_name_and_desc(help_attrs.commands)
"#{command_name_and_desc(help_attrs)}\n\n*Commands:*\n#{bot_commands_descs.join("\n")}"
end
end

private
def other_commands_descs
collect_name_and_desc(other_commands_help_attrs)
end

def command_name_and_desc(command_info)
desc = command_info[:desc].present? ? "- #{command_info[:desc]}" : ''
"*#{command_info[:title]}* #{desc}"
end
def command_full_desc(name)
unescaped_name = CGI.unescapeHTML(name)
help_attrs = find_command_help_attrs(unescaped_name)
return "There's no command *#{unescaped_name}*" unless help_attrs
return "There's no description for command *#{unescaped_name}*" if help_attrs.command_long_desc.blank?
"#{command_name_and_desc(help_attrs)}\n\n#{help_attrs.command_long_desc}"
end

def commands_info(command_classes)
commands_with_present_names = command_classes.select { |k| k.command_name.present? }
commands_with_present_names.inject([]) do |data, klass|
info = {}
HELP_ATTR_METHODS_MAP.each do |attr, setter_method|
info[setter_method] = klass.public_send(attr)
end
data << info
end
end
private

def bot_classes
all_command_classes.select { |k| k.superclass == SlackRubyBot::Bot }
end
def find_command_help_attrs(name)
help_attrs = commands_help_attrs.find { |k| k.command_name == name }
return help_attrs if help_attrs
commands_help_attrs.each { |k| k.commands.each { |c| return c if c.command_name == name } }
return nil
end

def command_classes_only
all_command_classes.reject { |k| k.superclass == SlackRubyBot::Bot }
def collect_help_attrs(help_attrs)
help_attrs_with_present_names(help_attrs).map do |help_attrs|
yield(help_attrs)
end
end

def all_command_classes
BUILTIN_COMMAND_CLASSES + external_command_classes
def collect_name_and_desc(help_attrs)
collect_help_attrs(help_attrs) do |help_attrs|
command_name_and_desc(help_attrs)
end
end

def command_classes
SlackRubyBot::Commands::Base.descendants
end
def command_name_and_desc(help_attrs)
desc = help_attrs.command_desc.present? ? "- #{help_attrs.command_desc}" : ''
"*#{help_attrs.command_name}* #{desc}"
end

def external_command_classes
command_classes.reject do |k|
k.name && k.name.start_with?('SlackRubyBot::Commands') || k == SlackRubyBot::Bot
end
end
def help_attrs_with_present_names(help_attrs)
help_attrs.select { |k| k.command_name.present? }
end

def bot_help_attrs
commands_help_attrs.select { |k| k.class_name.constantize.superclass == SlackRubyBot::Bot }
end

def other_commands_help_attrs
commands_help_attrs.select { |k| k.class_name.constantize.superclass == SlackRubyBot::Commands::Base }
end

end
end

0 comments on commit 239485b

Please sign in to comment.