]> git.somenet.org - irc/bugbot.git/blob - BotModules/Google.bm
GITOLITE.txt
[irc/bugbot.git] / BotModules / Google.bm
1 ################################
2 # Google Module                #
3 ################################
4
5 # Original Author: Max Kanat-Alexander <mkanat@bugzilla.org>
6 # Author: Stephen Lau <steve@grommit.com>
7 #
8 # stevel's notes:
9 # The original version of this module used Net::Google which used the Google
10 # SOAP API.  I've updated it to use the REST::Google::Search module which
11 # uses Google's AJAX API
12 #
13 # This API requires that you send a valid HTTP_REFERER, which you can set 
14 # with the REFERER constant below:
15
16 package BotModules::Google;
17 use vars qw(@ISA);
18 @ISA = qw(BotModules);
19 use REST::Google::Search;
20
21 use constant SEPARATOR => ' -- ';
22 use constant REFERER   => 'http://www.mozilla.org/projects/mozbot/';
23 1;
24
25 sub Help {
26     my $self = shift;
27     my ($event) = @_;
28     return {
29         '' =>    q{Queries Google for specified search terms. },
30         'google' =>  q{Searches google for the specified terms.}
31                    . q{Syntax: 'google <terms>'},
32                 'fight' => q{Google fight two terms.}
33                              . q{Syntax: 'fight <term1> vs. <term2>'}
34     };
35 }
36
37 # RegisterConfig - Called when initialised, should call registerVariables
38 sub RegisterConfig {
39     my $self = shift;
40     $self->SUPER::RegisterConfig(@_);
41     $self->registerVariables(
42       # [ name, save?, settable? ]
43       ['maxResults', 1, 1, 8],
44       ['maxInChannel', 1, 1, 1],
45       ['safeSearch', 1, 1, 1],
46       ['maxLineLength', 1, 1, 256]
47     );
48 }
49
50 sub Told {
51     my $self = shift;
52     my ($event, $message) = @_;
53     # We take anything that occurs at the end of the line,
54     # because Google will ignore punctuation anyway.
55     if ($message =~ /^(\s*google\s+)(.+)$/osi) {
56         my $terms = $2;
57
58         my @searchResults = $self->doSearch($terms);
59
60         if (!@searchResults) {
61             $self->say($event, "Nothing found.");
62         } 
63         # If we are in a channel, and not a /msg
64         elsif ($event->{'channel'}) {
65             splice(@searchResults, $self->{'maxInChannel'});
66         }
67         # We're in a /msg
68         else {
69             unshift(@searchResults, scalar(@searchResults) . " results found: ");
70         }
71
72         foreach my $result (@searchResults) {
73             $self->say($event, $event->{'from'} . ': ' . $result);
74         }
75     } elsif ($message =~ /^(\s*fight\s+)(.+)\s+vs\.\s+(.+)\s*$/osi) {
76                 my $term1 = $2;
77                 my $term2 = $3;
78                 my $results1 = $self->getNumResults($term1);
79                 my $results2 = $self->getNumResults($term2);
80
81                 if ($results1 > $results2) {
82                         $self->say($event, "\ 2$term1\ 2 beats $term2, \ 2$results1\ 2 to $results2!");
83                 } elsif ($results2 > $results1) {
84                         $self->say($event, "\ 2$term2\ 2 beats $term1, \ 2$results2\ 2 to $results1!");
85                 } else {
86                         $self->say($event, "It's a dead tie at \ 2$results1\ 2 results!");
87                 }
88         } else {
89         return $self->SUPER::Told(@_);
90     }
91     return 0; # we've dealt with it, no need to do anything else.
92 }
93
94 sub getNumResults {
95     my $self = shift;
96     my ($terms) = @_;
97         
98         REST::Google::Search->http_referer(REFERER);
99         my $res = REST::Google::Search->new(
100                 q => $terms,
101                 rsz => "large",
102         );
103
104         if ($res->responseStatus != 200) {
105                 return 0;
106         }
107
108         my $data = $res->responseData;
109         return $data->cursor->estimatedResultCount;
110 }
111 # Performs the actual Google search and returns the
112 # result as an array of lines to say.
113 sub doSearch {
114     my $self = shift;
115     my ($terms) = @_;
116
117     my @searchLines = ();
118         REST::Google::Search->http_referer(REFERER);
119         my $res = REST::Google::Search->new(
120                 q => $terms,
121                 rsz => "large",
122         );
123
124         if ($res->responseStatus != 200) {
125                 return @searchLines;
126         }
127
128         my $data = $res->responseData;
129         my @results = $data->results;
130
131     foreach my $result (@results) {
132         my $title = $result->title;
133         # The Google API puts <b></b> tags into the title if the search
134         # terms appear in the title.
135         $title =~ s|</?b>||g;
136         $title = $self->unescapeXML($title);
137         my $url = $result->url;
138         my $line_size = (length($title) + length($result) + length(SEPARATOR));
139         if ($line_size  > $self->{'maxLineLength'} ) {
140             # The 3 is for the '...'
141             my $new_title_size = ($line_size - $self->{'maxLineLength'}) - 3;
142             my $title = substr($title, 0, $new_title_size)
143                         . '...';
144         }
145         my $resultLine = $title . SEPARATOR . $url;
146         push(@searchLines, $resultLine);
147     }
148
149     return @searchLines;
150 }