Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

I heard you like brand spankin' new lookup stuff!

  • Loading branch information...
commit 97eebc7abdcfbc96a13e7b2a20340af73b2517db 1 parent ea194c5
@radar radar authored
View
1,935 leaves/logga/classes
1,935 additions, 0 deletions not shown
View
5 leaves/logga/config.rb
@@ -0,0 +1,5 @@
+require 'rubygems'
+require 'hpricot'
+require 'net/http'
+
+DEBUG = true
View
195 leaves/logga/controller.rb
@@ -3,6 +3,11 @@
class Controller < Autumn::Leaf
before_filter :check_for_new_day
+
+ def did_start_up
+ @classes = File.readlines("leaves/logga/classes").map { |line| line.split(" ")}
+ @methods = File.readlines("leaves/logga/methods").map { |line| line.split(" ")}
+ end
def who_command(stem, sender, reply_to, msg)
if authorized?(sender[:nick])
@@ -74,119 +79,130 @@ def update_api_command(stem, sender, reply_to, msg)
end
def lookup_command(stem, sender, reply_to, msg, opts={})
- return if msg.blank?
- parts = msg.split(" ") if msg.include?(" ")
- parts ||= msg.split("#") if msg.include?("#")
- parts ||= msg.gsub(/\(.*?\)/,'').split(".") if msg.include?(".")
- parts ||= [msg]
- @parts = parts
- @sender = sender
- @stem = stem
- @reply_to = reply_to
-
- # Is the first word a constant?
- if /^[A-Z]/.match(parts.first)
- constant = Constant.find_by_name(parts.first)
- constant ||= Constant.find_by_name(parts.first + "::ClassMethods")
- if constant
- entry = constant.entries.find_by_name(parts.last)
+ msg = msg.split(" ")[0..-1].map { |a| a.split("#") }.flatten!
+ # It's a constant! Oh... and there's nothing else in the string!
+ if /^[A-Z]/.match(msg.first) && msg.size == 1
+ object = find_constant(stem, sender, reply_to, msg.first)
+ # It's a method!
+ else
+ # Right, so they only specified one argument. Therefore, we look everywhere.
+ if msg.first == msg.last
+ object = find_method(stem, sender, reply_to, msg)
+ # Left, so they specified two arguments. First is probably a constant, so let's find that!
+ else
+ object = find_method(stem, sender, reply_to, msg.last, msg.first)
+ end
+ end
+ end
+
+
+ def find_constant(stem, sender, reply_to, name, entry=nil, opts={})
+ # Find by specific name.
+ constants = @classes.select { |c| c.first == name }
+ # Find by name beginning with <blah>.
+ constants = @classes.select { |c| /^#{name}.*/.match(c.first) } if constants.empty?
+ # Find by name containing letters of <blah> in order.
+ constants = @classes.select { |c| Regexp.new(name.split("").join(".*")).match(c.first) } if constants.empty?
+ if constants.size > 1
+ # Narrow it down to the constants that only contain the entry we are looking for.
+ if !entry.nil?
+ constants = constants.select { |constant| @methods.select { |m| m.first == entry && /#{entry} (#{constant.first})/.match([m.first, m[1]].join(" ")) } }
+ return [constants, constants.size]
+ else
+ display_constants(stem, sender, reply_to, constants, opts={})
+ end
+ if constants.size == 1
+ if entry.nil?
+ stem.message("#{opts[:directed_at] ? opts[:directed_at] + ":" : ''} #{constant}")
+ else
+ return [[constants.first], 1]
+ end
+ elsif constants.size == 0
if entry
- constant.increment!("count")
- entry.increment!("count")
- message = "#{constant.name}##{entry.name}: #{entry.url}"
- message = send_lookup_message(stem, message, reply_to, opts[:directed_at])
+ stem.message("There are no constants that match #{name} and contain #{entry}.", reply_to)
else
- if parts.last != parts.first
- entries = Entry.find_all_by_name(parts.last)
- if entries.empty?
- stem.message("Could not find any entry with the name #{parts.last} anywhere in the API.", sender[:nick])
- else
- classes_for(entries)
- end
- else
- constant.increment!("count")
- message = "#{constant.name}: #{constant.url}"
- send_lookup_message(stem, message, reply_to, opts[:directed_at])
- end
- end
- # When they specify an invalid constant (perhaps a partial name) and a valid entry.
- elsif parts.first != parts.last
- entries = Entry.find_all_by_name(parts.last)
- classes_for(entries)
- # When they specify an invalid constant AND an invalid entry.
+ stem.message("There are no constants that match #{name}", reply_to)
+ end
else
- stem.message("Could not find constant #{parts.first} or #{parts.first}::ClassMethods in the API!", sender[:nick])
+ return [constants, constants.size]
end
else
- # The first word is a method then
- entries = Entry.find_all_by_name(parts.first)
- if entries.size == 1
- entry = entries.first
- constant = entry.constant
- constant.increment!("count")
- entry.increment!("count")
- message = "#{constant.name}##{entry.name}: #{entry.url}"
- message = send_lookup_message(stem, message, reply_to, opts[:directed_at])
- elsif entries.size > 1
- classes_for(entries)
-
+ if entry.nil?
+ display_constants(stem, sender, reply_to, constants, opts={})
else
- stem.message("Could not find any entry with the name #{parts.last} anywhere in the API.", sender[:nick])
+ return [[constants.first], 1]
+ end
+ end
+ end
+
+ # Find an entry.
+ # If the constant argument is passed, look it up within the scope of the constant.
+ def find_method(stem, sender, reply_to, name, constant=nil, opts={})
+ if constant
+ constants, number = find_constant(stem, sender, reply_to, constant, name)
+ end
+ methods = []
+ methods = @methods.select { |m| m.first == name}
+ methods = @methods.select { |m| /#{name}.*/.match(m.first) } if methods.empty?
+ methods = @methods.select { |m| Regexp.new(name.split("").join(".*")).match(m.first) } if methods.empty?
+ if constant
+ methods = methods.select { |m| /#{constants.join("|")}/.match(m[1]) }
+ end
+ count = 0
+ if methods.size == 1
+ method = methods.first
+ stem.message("#{opts[:directed_at] ? opts[:directed_at] + ":" : ''} #{method[1].gsub(/[\(|\)]/, '')}##{method.first} #{method.last}", reply_to)
+ elsif methods.size <= 3
+ for method in methods
+ stem.message("#{opts[:directed_at] ? opts[:directed_at] + ":" : ''} #{count += 1}. #{method[1].gsub(/[\(|\)]/, '')}##{method.first} #{method.last}", reply_to)
end
+ methods
+ else
+ stem.message("#{sender[:nick]}: Please be more specific.", reply_to)
end
+ return nil
end
- def google_command(stem, sender, reply_to, msg, opts={})
- google("http://www.google.com/search", stem, sender, msg, reply_to, opts)
+ def display_constants(stem, sender, reply_to, constants, opts={})
+ count = 0
+ if constants.size == 1
+ constant = constants.first
+ message = "#{opts[:directed_at] ? opts[:directed_at] + ":" : ''} #{constant.first} #{constant.last}"
+ stem.message(message, reply_to)
+ elsif constants.size <= 3
+ for constant in constants
+ message = "#{opts[:directed_at] ? opts[:directed_at] + ":" : ''} #{count+=1}. #{constant.first} #{constant.last}"
+ stem.message(message, reply_to)
+ end
+ else
+ stem.message("#{sender[:nick]}: Please refine your query, we found #{constants.size} constants (threshold is 3).", reply_to)
+ end
+ return nil
end
- alias :g_command :google_command
- def gg_command(stem, sender, reply_to, msg, opts={})
- google("http://www.letmegooglethatforyou.com/", stem, sender, msg, reply_to, opts)
+ def google_command(stem, sender, reply_to, msg, opts={})
+ search("http://www.google.com/search", stem, sender, msg, reply_to, opts)
end
- private
-
- # Lookup stuff
-
- def send_lookup_message(stem, message, reply_to, directed_at=nil)
- message = "#{directed_at}: " + message if directed_at
- stem.message(message, reply_to)
- end
+ alias :g_command :google_command
- def update_api(name, url)
- Api.find_or_create_by_name_and_url(name, url)
- update_methods(Hpricot(Net::HTTP.get(URI.parse("#{url}/fr_method_index.html"))), url)
- update_classes(Hpricot(Net::HTTP.get(URI.parse("#{url}/fr_class_index.html"))), url)
+ def gg_command(stem, sender, reply_to, msg, opts={})
+ search("http://www.letmegooglethatforyou.com/", stem, sender, msg, reply_to, opts)
end
- def update_methods(doc, prefix)
- doc.search("a").each do |a|
- names = a.inner_html.split(" ")
- method = names[0]
- name = names[1].gsub(/[\(|\)]/, "")
- # The same constant can be defined twice in different APIs, be wary!
- url = prefix + "/classes/" + name.gsub("::", "/") + ".html"
- constant = Constant.find_or_create_by_name_and_url(name, url)
- constant.entries.create!(:name => method, :url => prefix + "/" + a["href"])
- end
+ def railscast_command(stem, sender, reply_to, msg, opts={})
+ search("http://railscasts.com/episodes", stem, sender, msg, reply_to, opts, "search")
end
- def update_classes(doc, prefix)
- doc.search("a").each do |a|
- constant = Constant.find_or_create_by_name_and_url(a.inner_html, a["href"])
- end
- end
+ private
- # Ye olde Google.
- def google(host, stem, sender, msg, reply_to, opts)
- return unless authorized?(sender[:nick])
- message = "#{host}?q=#{msg.split(" ").join("+")}"
+ def search(host, stem, sender, msg, reply_to, opts, query_parameter="q")
+ message = "#{host}?#{query_parameter}=#{msg.split(" ").join("+")}"
if opts[:directed_at]
message = opts[:directed_at] + ": #{message}"
- stem.message(message)
+ stem.message(message, reply_to)
else
return message
end
@@ -252,7 +268,6 @@ def did_receive_channel_message(stem, sender, channel, message)
end
# Log Chat Line
- puts "Creating chat line..."
chat = person.chats.create(:channel => channel, :message => message, :message_type => "message", :other_person => other_person)
## Did the person thank another person?
View
72 leaves/logga/lookup.rb
@@ -0,0 +1,72 @@
+#!/usr/bin/ruby
+LIB_DIR = File.dirname(__FILE__)
+
+CLASSES = File.join(LIB_DIR, "classes")
+METHODS = File.join(LIB_DIR, "methods")
+DECENT_OPERATING_SYSTEM = RUBY_PLATFORM =~ /darwin/
+
+require File.join(LIB_DIR, "config")
+
+# Updates blazingly fast now.
+def update
+ puts "UPDATING..."
+ f = File.open(CLASSES, "w+")
+ f.close
+ f = File.open(METHODS, "w+")
+ f.close
+ update_api("http://api.rubyonrails.org/")
+ update_api("http://ruby-doc.org/core/")
+end
+
+def update_api(url)
+ update_classes(url)
+ update_methods(url)
+end
+
+def update_classes(url)
+ c = File.open(CLASSES,"a+")
+ classes = File.readlines(CLASSES)
+ doc = Hpricot(Net::HTTP.get(URI.parse("#{url}/fr_class_index.html")))
+ doc.search("a").each do |a|
+ puts "#{a.inner_html}"
+ c.write "#{a.inner_html} #{url + a['href']}\n" if !classes.include?(a.inner_html)
+ end
+end
+
+def update_methods(url)
+ c = File.open(CLASSES, "a+")
+ classes = File.readlines(CLASSES)
+ e = File.open(METHODS, "a+")
+ methods = File.readlines(METHODS)
+ doc = Hpricot(Net::HTTP.get(URI.parse("#{url}/fr_method_index.html")))
+ doc.search("a").each do |a|
+ constant_name = a.inner_html.split(" ")[1].gsub(/[\(|\)]/, "")
+ if /^[A-Z]/.match(constant_name)
+ e.write "#{a.inner_html} #{url + a['href']}\n"
+ end
+ end
+end
+
+
+
+
+ def lookup
+ @classes = File.readlines(CLASSES).map { |line| line.split(" ")}
+ @methods = File.readlines(METHODS).map { |line| line.split(" ")}
+ parts = ARGV[0..-1].map { |a| a.split("#") }.flatten!
+
+ # It's a constant! Oh... and there's nothing else in the string!
+ if /^[A-Z]/.match(parts.first) && parts.size == 1
+ object = find_constant(parts.first)
+ # It's a method!
+ else
+ # Right, so they only specified one argument. Therefore, we look everywhere.
+ if parts.first == parts.last
+ object = find_method(parts.first)
+ # Left, so they specified two arguments. First is probably a constant, so let's find that!
+ else
+ object = find_method(parts.last, parts.first)
+ end
+ end
+ end
+ lookup
View
9,990 leaves/logga/methods
9,990 additions, 0 deletions not shown
View
3  leaves/logga/models/api.rb
@@ -0,0 +1,3 @@
+class Api < ActiveRecord::Base
+ has_many :namespaces
+end
View
6 leaves/logga/models/constant.rb
@@ -1,5 +1,9 @@
-# Class is already taken!
class Constant < ActiveRecord::Base
has_many :entries
+ belongs_to :namespace
validates_presence_of :name
+
+ def to_s
+ "#{name}: #{url}"
+ end
end
View
10 leaves/logga/models/entry.rb
@@ -1,4 +1,14 @@
class Entry < ActiveRecord::Base
belongs_to :constant
validates_presence_of :name, :url
+
+ def to_s
+ "#{with_constant}: #{url}"
+ end
+
+ def with_constant
+ "#{constant.name}##{name}"
+ end
+
+
end
View
4 leaves/logga/models/namespace.rb
@@ -0,0 +1,4 @@
+class Namespace < ActiveRecord::Base
+ belongs_to :api
+ has_many :constants
+end
Please sign in to comment.
Something went wrong with that request. Please try again.