diff --git a/mozilla/webtools/mozbot/BotModules/Google.bm b/mozilla/webtools/mozbot/BotModules/Google.bm new file mode 100644 index 00000000000..c7053777cbb --- /dev/null +++ b/mozilla/webtools/mozbot/BotModules/Google.bm @@ -0,0 +1,117 @@ +################################ +# Google Module # +################################ + +# Author: Max Kanat-Alexander + +# Uses the Net::Google module to query Google for keywords. +# Note that Net::Google requires SOAP::Lite. + +package BotModules::Google; +use vars qw(@ISA); +@ISA = qw(BotModules); +use Net::Google; + +use constant SEPARATOR => ' -- '; +1; + +sub Help { + my $self = shift; + my ($event) = @_; + return { + '' => q{Queries Google for specified search terms. Note that you} + . q{ have to specify your Google API Key (the 'googleApiKey'} + . q{ var) before using any commands. To get a Google API Key,} + . q{ see: http://www.google.com/apis/ and go to "Create an} + . q{ Account."}, + 'google' => q{Searches google for the specified terms.} + . q{Syntax: 'google '}, + }; +} + +# RegisterConfig - Called when initialised, should call registerVariables +sub RegisterConfig { + my $self = shift; + $self->SUPER::RegisterConfig(@_); + $self->registerVariables( + # [ name, save?, settable? ] + ['maxResults', 1, 1, 10], + ['maxInChannel', 1, 1, 1], + # XXX - Not yet implemented. + #['backoffTime', 1, 1, 120], + ['googleApiKey', 1, 1, ''], + ['safeSearch', 1, 1, 1], + # Note that maxLineLength will not be respected if the URL + # alone is longer than maxLineLength. + ['maxLineLength', 1, 1, 256] + ); +} + +sub Told { + my $self = shift; + my ($event, $message) = @_; + # We take anything that occurs at the end of the line, + # because Google will ignore punctuation anyway. + if ($message =~ /^(\s*google\s+)(.+)$/osi) { + my $terms = $2; + + my @searchResults = $self->doSearch($terms); + + if (!@searchResults) { + $self->say($event, "Nothing found."); + # XXX - We could use $google->spell here to make suggestions. + } + # If we are in a channel, and not a /msg + elsif ($event->{'channel'}) { + splice(@searchResults, $self->{'maxInChannel'}); + } + # We're in a /msg + else { + unshift(@searchResults, scalar(@searchResults) . " results found: "); + } + + foreach my $result (@searchResults) { + $self->say($event, $event->{'from'} . ': ' . $result); + } + } else { + return $self->SUPER::Told(@_); + } + return 0; # we've dealt with it, no need to do anything else. +} + + +# Performs the actual Google search and returns the +# result as an array of lines to say. +sub doSearch { + my $self = shift; + my ($terms) = @_; + + my $google = Net::Google->new(key => $self->{'googleApiKey'}); + my $search = $google->search(safe => $self->{'safeSearch'}, + filter => $self->{'safeSearch'}, + max_results => $self->{'maxResults'}); + $search->query($terms); + my $results = $search->results(); + + my @searchLines = (); + + foreach my $result (@$results) { + my $title = $result->title(); + # The Google API puts tags into the title if the search + # terms appear in the title. + $title =~ s|||g; + $title = $self->unescapeXML($title); + my $url = $result->URL(); + my $line_size = (length($title) + length($result) + length(SEPARATOR)); + if ($line_size > $self->{'maxLineLength'} ) { + # The 3 is for the '...' + my $new_title_size = ($line_size - $self->{'maxLineLength'}) - 3; + my $title = substr($title, 0, $new_title_size) + . '...'; + } + my $resultLine = $title . SEPARATOR . $url; + push(@searchLines, $resultLine); + } + + return @searchLines; +}