psychoticwolf%carolina.rr.com d1e11d8c4d Bug 490421 - Add extended search to Google.bm. Patch by Jesse Pearson <jesall@gmail.com> and Tanner M. Young <mozilla.bugs@alyoung.com>, r=Wolf
git-svn-id: svn://10.0.0.236/trunk@260128 18797224-902f-48f8-a5cc-f745e15eee43
2010-04-02 19:42:21 +00:00

196 lines
6.3 KiB
Plaintext

################################
# Google Module #
################################
# Original Author: Max Kanat-Alexander <mkanat@bugzilla.org>
# Author: Stephen Lau <steve@grommit.com>
#
# stevel's notes:
# The original version of this module used Net::Google which used the Google
# SOAP API. I've updated it to use the REST::Google::Search module which
# uses Google's AJAX API
#
# This API requires that you send a valid HTTP_REFERER, which you can set
# with the REFERER constant below:
package BotModules::Google;
use vars qw(@ISA);
@ISA = qw(BotModules);
use REST::Google::Search;
use constant SEPARATOR => ' -- ';
use constant REFERER => 'http://www.mozilla.org/projects/mozbot/';
1;
sub Help {
my $self = shift;
my ($event) = @_;
return {
'' => q{Queries Google for specified search terms.},
'google' => q{Searches google for the specified terms.}
. q{Syntax: 'google <terms>'},
'web' => q{Searches google for the specified terms.}
. q{Syntax: 'web <terms>'},
'fight' => q{Google fight two terms.}
. q{Syntax: 'fight <term1> vs. <term2>'},
'images' => q{Queries google images for the specified terms.}
. q{ Syntax: 'images <terms>'},
'maps' => q{Queries google maps for the specified terms.}
. q{ Syntax: 'maps <terms>'},
'news' => q{Queries google news for the specified terms.}
. q{ Syntax: 'news <terms>'},
'video' => q{Queries google video for the specified terms.}
. q{ Syntax: 'video <terms>'}
};
}
# RegisterConfig - Called when initialised, should call registerVariables
sub RegisterConfig {
my $self = shift;
$self->SUPER::RegisterConfig(@_);
$self->registerVariables(
# [ name, save?, settable? ]
['maxResults', 1, 1, 8],
['maxInChannel', 1, 1, 1],
['safeSearch', 1, 1, 1],
['maxLineLength', 1, 1, 256],
['searchSites', 1, 1, {}]
);
}
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*fight\s+)(.+)\s+vs\.\s+(.+)\s*$/osi) {
my $term1 = $2;
my $term2 = $3;
my $results1 = $self->getNumResults($term1);
my $results2 = $self->getNumResults($term2);
if ($results1 > $results2) {
$self->say($event, "$term1 beats $term2, $results1 to $results2!");
} elsif ($results2 > $results1) {
$self->say($event, "$term2 beats $term1, $results2 to $results1!");
} else {
$self->say($event, "It's a dead tie at $results1 results!");
}
} elsif ($message =~ /^\s*(\w+)\s+(.+)$/osi) {
my $site = $1;
my $terms = $2;
my @searchResults = {};
if ($site =~ /^video$/ios) {
@searchResults = $self->doSearch("VIDEO",$terms);
} elsif ($site =~ /^news$/ios) {
@searchResults = $self->doSearch("NEWS", $terms);
} elsif ($site =~ /^images$/ios) {
@searchResults = $self->doSearch("IMAGES", $terms);
} elsif ($site =~ /^maps$/ios) {
@searchResults = $self->doSearch("LOCAL", $terms);
} elsif ($site =~ /^google|web$/ios or grep {/^$site$/is} keys (%{$self->{'searchSites'}})){
$terms .= ' site:'.$self->{'searchSites'}{$site} unless $site =~ /^google$/ios;
@searchResults = $self->doSearch("WEB",$terms);
}
else {
return $self->SUPER::Told(@_);
}
if (!@searchResults) {
$self->say($event, "Nothing found.");
}
# 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.
}
sub getNumResults {
my $self = shift;
my ($terms) = @_;
REST::Google::Search->http_referer(REFERER);
my $res = REST::Google::Search->new(
q => $terms,
rsz => "large",
);
if ($res->responseStatus != 200) {
return 0;
}
my $data = $res->responseData;
return $data->cursor->estimatedResultCount;
}
# Performs the actual Google search and returns the
# result as an array of lines to say.
sub doSearch {
my $self = shift;
my ($type, $terms) = @_;
my @searchLines = ();
if ($type eq "IMAGES") {
use REST::Google::Search qw/IMAGES/;
REST::Google::Search->service(IMAGES);
} elsif ($type eq "VIDEO") {
use REST::Google::Search qw/VIDEO/;
REST::Google::Search->service(VIDEO);
} elsif ($type eq "NEWS") {
use REST::Google::Search qw/NEWS/;
REST::Google::Search->service(NEWS);
} elsif ($type eq "LOCAL") {
use REST::Google::Search qw/LOCAL/;
REST::Google::Search->service(LOCAL);
} else {
use REST::Google::Search qw/WEB/;
REST::Google::Search->service(WEB);
}
REST::Google::Search->http_referer(REFERER);
my $res = REST::Google::Search->new(
q => $terms,
rsz => "large",
);
if ($res->responseStatus != 200) {
return @searchLines;
}
my $data = $res->responseData;
my @results = $data->results;
foreach my $result (@results) {
my $title = $result->title;
# The Google API puts <b></b> tags into the title if the search
# terms appear in the title.
$title =~ s|</?b>||g;
$title = $self->unescapeXML($title);
my $url = $result->url;
$url =~ s/%([0-9A-F]{2})/chr(hex($1))/egi;
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;
}