Skip to content
This repository has been archived by the owner on Jun 30, 2022. It is now read-only.

Commit

Permalink
Merge pull request #19 from webdestroya/web-help
Browse files Browse the repository at this point in the history
Ability to reply to 'help' with a URL containing a list of commands
  • Loading branch information
jimmycuadra committed Oct 4, 2013
2 parents 6f87c99 + 7e19f9c commit 099bb42
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 6 deletions.
25 changes: 25 additions & 0 deletions lib/lita.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
require "redis-namespace"
require "thin"

require "erb"
require "cgi"
require "uri"

# The main namespace for Lita. Provides a global registry of adapters and
# handlers, as well as global configuration, logger, and Redis store.
module Lita
Expand Down Expand Up @@ -87,6 +91,27 @@ def run(config_path = nil)
Config.load_user_config(config_path)
Robot.new.run
end

# The root template path
# @return [String]
def template_root
@template_root ||= begin
this_file = File.expand_path(__FILE__)
File.expand_path('../templates', File.dirname(this_file))
end
end

# Builds a URL that can be used to access the web pages of Lita
# @param path [String] the path to build a URL for
# @return [String]
def url_for(path="")
if Lita.config.public_url.nil?
uri = URI.parse("#{Lita.config.public_url}/#{path.gsub(/^\/+/,'')}")
return uri.path
end

URI.join(Lita.config.public_url, path).to_s
end
end
end

Expand Down
63 changes: 57 additions & 6 deletions lib/lita/handlers/help.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,83 @@ class Help < Handler
}.gsub(/\n/, "")
})

http.get "/lita/help", :web_help

# Outputs help information about Lita commands.
# @param response [Lita::Response] The response object.
# @return [void]
def help(response)
output = build_help(response)
output = filter_help(output, response)

output.map! do |command|
"#{command[:command]} - #{command[:description]}"
end

if Lita.config.public_url
output.unshift <<-REPLY.chomp
View the list of commands at #{Lita.url_for("/lita/help")}
REPLY
end

response.reply_privately output.join("\n")
end

# Provides a formatted HTML page listing available chat commands.
#
# @note If you want all +help+ requests to be given a URL with
# a list of commands rather than listing them within the chat
# then you must specify the publicly accessible URL for your
# chat bot using +Lita.config.public_url+ within
# +lita_config.rb+
#
# @example Sample configuration
# # lita_config.rb
# Lita.configure do |config|
# ...
# config.public_url = "http://my-lita-bot.herokuapp.com"
# ...
# end
#
# @param request [Rack::Request] The request object.
# @param response [Rack::Response] The response object.
# @return [void]
def web_help(request, response)
response.headers["Content-Type"] = "text/html"
tpl_file = File.join Lita.template_root, 'handlers/help/help.html.erb'

@commands = build_help

response.write ERB.new(File.read(tpl_file)).result(binding)
rescue
response.write <<-REPLY.chomp
Sorry, but there was a problem generating the list of commands.
REPLY
end

private

# Checks if the user is authorized to at least one of the given groups.
def authorized?(user, required_groups)
def authorized?(response, required_groups)
required_groups.nil? || required_groups.any? do |group|
Lita::Authorization.user_in_group?(user, group)
return false if response.nil?
Lita::Authorization.user_in_group?(response.user, group)
end
end

# Creates an array of help info for all registered routes.
def build_help(response)
def build_help(response=nil)
output = []

Lita.handlers.each do |handler|
handler.routes.each do |route|
route.help.each do |command, description|
next unless authorized?(response.user, route.required_groups)
next unless authorized?(response, route.required_groups)
command = "#{name}: #{command}" if route.command?
output << "#{command} - #{description}"
output << {
:command => command,
:description => description
}
end
end
end
Expand All @@ -51,7 +100,9 @@ def filter_help(output, response)
filter = response.matches[0][0]

if filter
output.select { |line| /(?:@?#{name}[:,]?)?#{filter}/i === line }
output.select do |line|
/(?:@?#{name}[:,]?)?#{filter}/i === line[:command]
end
else
output
end
Expand Down
14 changes: 14 additions & 0 deletions spec/lita/handlers/help_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
it { routes_command("help").to(:help) }
it { routes_command("help foo").to(:help) }

it { routes_http(:get, "/lita/help").to(:web_help) }

describe "#help" do
let(:secret_handler_class) do
Class.new(Lita::Handler) do
Expand Down Expand Up @@ -34,4 +36,16 @@
expect(replies.last).not_to include("secret")
end
end

describe "#web_help" do
it "ensures that calling help with the config option set works" do
Lita.configure do |config|
config.public_url = "http://litabot"
end

send_command("help")
expect(replies.last).to match(/^View the list of commands at /)
expect(replies.last).to match(/http:\/\/litabot\/lita\/help$/)
end
end
end
21 changes: 21 additions & 0 deletions spec/lita_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,27 @@
expect(described_class.config).to eql(described_class.config)
end

it "memoizes a template root" do
expect(described_class.template_root).to match(/lita\/templates$/)
end

describe ".url_for" do
it "returns a relative url when public_url is blank" do
expect(described_class.url_for).to eq("/")
expect(described_class.url_for("/")).to eq("/")
expect(described_class.url_for("/lita/help")).to eq("/lita/help")
expect(described_class.url_for("/h/p")).to eq("/h/p")
end

it "returns an absolute url when public_url is set" do
described_class.configure { |c| c.public_url = "http://lita.io/" }
expect(described_class.url_for).to eq("http://lita.io/")
expect(described_class.url_for("/")).to eq("http://lita.io/")
expect(described_class.url_for("/help")).to eq("http://lita.io/help")
expect(described_class.url_for("/h/p")).to eq("http://lita.io/h/p")
end
end

describe ".configure" do
it "yields the Config object" do
described_class.configure { |c| c.robot.name = "Not Lita" }
Expand Down
23 changes: 23 additions & 0 deletions templates/handlers/help/help.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE>
<html>
<head>
<title><%= Lita.config.robot.name %> Available Commands</title>
<style>
body {font-size:120%;}
dt {font-family: monospace;font-weight:bold;font-size:125%;}
dd {margin-bottom:0.5em;font-style: italic;}
</style>
</head>
<body>
<h1><%= Lita.config.robot.name %> Available Commands</h1>

<p>The list below contains the possible commands and phrases that <code><%= Lita.config.robot.name %></code> can respond to.</p>

<dl>
<% @commands.each do |command| %>
<dt><%= CGI.escapeHTML(command[:command]) %></dt>
<dd><%= CGI.escapeHTML(command[:description]) %></dd>
<% end %>
</dl>
</body>
</html>

0 comments on commit 099bb42

Please sign in to comment.